gpt4 book ai didi

iOS - swift - 为 secp224k1 曲线(ECDH)生成 key 对

转载 作者:行者123 更新时间:2023-12-03 03:24:06 25 4
gpt4 key购买 nike

我一直在尝试在 iOS 中为 secp224k1 曲线生成公钥和私钥。我们使用 ECDH 方法在移动端和后端之间进行 api 握手。在 Java 中,它是使用以下代码完成的。

public static KeyPair getECKeyPair() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp224k1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDH", "SC");
kpg.initialize(ecSpec);
return kpg.generateKeyPair();
}

有没有办法在 swift 中生成具有特定曲线(secp224k1)类型的 key ?我尝试使用苹果提供的 EC 算法通过以下代码进行握手。

    //Generates public and private key with EC algorithm
public static func getKey() -> [String: SecKey]? {

let attributes: [String: Any] =
[kSecAttrKeySizeInBits as String: 256,
kSecAttrKeyType as String: kSecAttrKeyTypeEC,
kSecPrivateKeyAttrs as String:
[kSecAttrIsPermanent as String: false]
]
var error: Unmanaged<CFError>?
guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
let err = error!.takeRetainedValue() as Error
print(err.localizedDescription)
return nil
}
guard let publicKey = SecKeyCopyPublicKey(privateKey) else {
print("Error occured while creating public key")
return nil
}
return ["publicKey": publicKey, "privateKey": privateKey]
}

当我发送通过上述方法生成的公钥时,我从服务器收到一条错误消息:

"error":"java.security.InvalidKeyException: ECDH key agreement requires ECPublicKey for doPhase","exception":"InvalidAuthException"

我尝试了 VirgilCrypto 来快速解决问题。但它在库中没有我需要的特定曲线类型。它仅支持 secp256r1。另外,我尝试过以下帖子的答案,但没有成功。

Elliptic Curve Diffie Hellman in ios/swift

任何建议或帮助都会很棒,谢谢。

最佳答案

iOS 不支持 Koblitz 224 位曲线。一种解决方案可能是使用不同的曲线类型或支持 secp224k1 的第三方库。

根据您的评论可以得出结论,secp224k1 曲线类型是必需的。

可能使用的第三方库是 Virgil Crypto,可通过 github https://github.com/VirgilSecurity/virgil-crypto 获取。 。它是一个 C++ 库。 (Virgil Security 还提供了一个名为 virgil-crypto-x 的 Swift 包装器库,但该库在当前版本中不再支持 secp224k1)。

通过创建具有已定义接口(interface)的 Objective-C++ 包装器,可以在 Swift 中间接使用 C++ 库。

构建 VSCCrypto.framework

在命令行输入:

git clone https://github.com/VirgilSecurity/virgil-crypto
cd virgil-crypto
utils/build.sh --target=ios

这构建了 iOS 的框架。

将 VSCCrypto.framework 添加到 Xcode 项目

  • 在项目导航器中选择根节点
  • 在 Xcode 中创建“新组”
  • 将其命名为“框架”
  • 在 Finder 中将 virgil-crypto/build/ios/lib 文件夹中的 VSCCrypto.framework 拖放到“Frameworks”组

  • 在 XCode 中,点击右侧“嵌入式二进制文件”下的加号

  • 选择 VSCCrypto.framework

Objective-C++ 包装器

  • 创建 ECDHCrypto Objective-C 文件
  • 当系统询问“您想要配置 Objective-C 桥接 header 吗”时,请点击“创建桥接 header ”
  • 在项目导航器中将文件后缀从 .m 更改为 .mm(以允许其中使用 C++ 代码)
  • #import "ECDHCrypto.h" 添加到桥接 header

ECDHCrypto.h

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface ECDHCrypto : NSObject

@property(nonatomic, strong) NSString *ownPrivateKey;
@property(nonatomic, strong) NSString *ownPublicKey;

- (void)generateKeyPair;
- (NSString *)shared:(NSString *)otherPublicKey;

@end

NS_ASSUME_NONNULL_END

ECDHCrypto.mm

#import "ECDHCrypto.h"
#import <VSCCrypto/VirgilCrypto.h>

using virgil::crypto::VirgilKeyPair;
using virgil::crypto::VirgilByteArray;
using virgil::crypto::VirgilCipherBase;
using virgil::crypto::str2bytes;
using virgil::crypto::bytes2str;
using virgil::crypto::bytes2hex;


@implementation ECDHCrypto

- (void)generateKeyPair {
VirgilKeyPair keyPair = VirgilKeyPair::generate(VirgilKeyPair::Type::EC_SECP224K1);

VirgilByteArray ownPublicKeyBates = keyPair.publicKey();
self.ownPublicKey = [NSString stringWithCString:bytes2str(ownPublicKeyBates).c_str()
encoding:[NSString defaultCStringEncoding]];

VirgilByteArray ownPrivateKeyBytes = keyPair.privateKey();
self.ownPrivateKey = [NSString stringWithCString:bytes2str(ownPrivateKeyBytes).c_str()
encoding:[NSString defaultCStringEncoding]];
}

- (NSString *)shared:(NSString *)otherPublicKey {
NSAssert(self.ownPrivateKey, @"private key must be set, e.g. use generateKeyPair");
std::string otherPKString([otherPublicKey cStringUsingEncoding:NSASCIIStringEncoding]);
VirgilByteArray pubKey = str2bytes(otherPKString);

std::string ownPrivateKeyString([self.ownPrivateKey cStringUsingEncoding:NSASCIIStringEncoding]);
VirgilByteArray ownPrivateKeyBytes = str2bytes(ownPrivateKeyString);

VirgilByteArray shared_ba = VirgilCipherBase::computeShared(pubKey, ownPrivateKeyBytes);

std::string hex = bytes2hex(shared_ba);
NSString *shared = [NSString stringWithCString:hex.c_str()
encoding:[NSString defaultCStringEncoding]];

return shared;
}

@end

Swift 中的用法

let otherPK = """
-----BEGIN PUBLIC KEY-----
ME4wEAYHKoZIzj0CAQYFK4EEACADOgAEgeW/foqxCDOd1y6lnXONkRThS6xhjLHP
SEXs7jHSpoaPQH4vArcGmIb1cAZcepEh7WDQxCyfQXg=
-----END PUBLIC KEY-----
"""

let ecdhCrypto = ECDHCrypto()
ecdhCrypto.generateKeyPair();
print("ecdhCrypto.ownPublicKey: \n" + ecdhCrypto.ownPublicKey);
print("shared secret: " + ecdhCrypto.shared(otherPK));

使用 Java 对应程序进行测试

要测试 key 交换是否成功,可以执行以下测试:

  1. Java中会生成secp224k1 key 对,并将公钥输出到控制台。

  2. 使用复制/粘贴将公钥复制到 iOS 应用程序的 Swift 代码中。然后,应用程序生成 key 对并将其自己的公钥以及计算出的共享 key 写入控制台。然后,iOS 公钥将作为输入插入到 Java 程序中(以绿色显示)。

  3. 最后,我们可以比较 iOS 应用程序和 Java 程序的共享 key 。这里也是一样,所以 key 交换成功。

在上部区域中,您可以看到带有 iOS 源代码的 Xcode,在下部区域中可以看到 Java 程序的输出:

same shared secret

关于iOS - swift - 为 secp224k1 曲线(ECDH)生成 key 对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58138190/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com