swift 使用 ECDH 生成共享密钥
swift Generate shared key using ECDH
我正在尝试加密发送到服务器的消息。
为此,我生成了一个 public 和私钥。
我将我的 public 密钥发送到服务器并从中接收它的 public 密钥。
func generatePair() {
if let crypto = GMEllipticCurveCrypto.generateKeyPair(for: GMEllipticCurveSecp256r1) {
crypto.compressedPublicKey = false
curveCrypto = crypto
if let publicKey = crypto.publicKey {
let pub = Data(publicKey[1...publicKey.count-1])
self.publicKey = pub.base64EncodedString()
self.privateKey = crypto.privateKeyBase64
}
}
}
收到后,我尝试生成一个共享密钥来加密数据。
func generateSecret(withKey key: String) {
guard let crypto = curveCrypto else {
return
}
print("generateSecret \(key)")
sharedKey = crypto.sharedSecret(forPublicKeyBase64: key)
}
但是我在行中得到了错误 (sharedKey = crypto.sharedSecret(forPublicKeyBase64: key))
*** Terminating app due to uncaught exception 'Invalid Key', reason: 'Public key {length = 64, bytes = 0xace3000d e1483ed9 82d88432 9397c716 ... d64e0fe1 47920d9f } is invalid'
我的 public 密钥和服务器密钥的长度相同。
我做错了什么?
我相信您正在使用 ricmoo 的 GMEllipticCurveCrypto。
此框架在内部使用压缩密钥。这就是为什么它总是会失败,因为输入密钥的长度 (65) 与压缩密钥的预期长度 (33) 不匹配。
请注意,函数 sharedSecret(forPublicKeyBase64:)
将在内部调用 sharedSecret(forPublicKey:)
。所以最终的解决方案是在将密钥传递给sharedSecret(forPublicKey:)
之前再次压缩密钥。您可以选择在头文件中公开 compressPublicKey
函数,或者使用以下解决方案更新 .m 文件中的函数。
原文:
// Prepare the public key
- (NSData*)sharedSecretForPublicKey: (NSData*)otherPublicKey {
[...]
uint8_t l_other_public[_bytes + 1];
if ([otherPublicKey length] != _bytes + 1) {
[NSException raise:@"Invalid Key" format:@"Public key %@ is invalid", otherPublicKey];
}
[...]
}
修复:
- (NSData*)sharedSecretForPublicKey: (NSData*)otherPublicKey {
NSData* compressedKey = [self compressPublicKey:otherPublicKey];
[...]
// Prepare the public key
uint8_t l_other_public[_bytes + 1];
if ([compressedKey length] != _bytes + 1) {
[NSException raise:@"Invalid Key" format:@"Public key %@ is invalid", compressedKey];
}
[compressedKey getBytes:&l_other_public length:[compressedKey length]];
[...]
}
终于找到解决方法了
从服务器收到 public 密钥后,我应该这样做:
private func getPublicKey(publicKey: String) -> String? {
if let publicKeyData = Data(base64Encoded: publicKey) {
var newKeyData = publicKeyData
newKeyData.insert(0x04, at: 0)
if let compressKeyData = curveCrypto?.compressPublicKey(newKeyData) {
return compressKeyData.base64EncodedString()
} else {
print("PUB KEY ERROR: compressKeyData")
return nil
}
} else {
print("PUB KEY ERROR: b64")
return nil
}
}
并且这个 public 密钥应该用于生成共享密钥。
我正在尝试加密发送到服务器的消息。 为此,我生成了一个 public 和私钥。 我将我的 public 密钥发送到服务器并从中接收它的 public 密钥。
func generatePair() {
if let crypto = GMEllipticCurveCrypto.generateKeyPair(for: GMEllipticCurveSecp256r1) {
crypto.compressedPublicKey = false
curveCrypto = crypto
if let publicKey = crypto.publicKey {
let pub = Data(publicKey[1...publicKey.count-1])
self.publicKey = pub.base64EncodedString()
self.privateKey = crypto.privateKeyBase64
}
}
}
收到后,我尝试生成一个共享密钥来加密数据。
func generateSecret(withKey key: String) {
guard let crypto = curveCrypto else {
return
}
print("generateSecret \(key)")
sharedKey = crypto.sharedSecret(forPublicKeyBase64: key)
}
但是我在行中得到了错误 (sharedKey = crypto.sharedSecret(forPublicKeyBase64: key))
*** Terminating app due to uncaught exception 'Invalid Key', reason: 'Public key {length = 64, bytes = 0xace3000d e1483ed9 82d88432 9397c716 ... d64e0fe1 47920d9f } is invalid'
我的 public 密钥和服务器密钥的长度相同。
我做错了什么?
我相信您正在使用 ricmoo 的 GMEllipticCurveCrypto。
此框架在内部使用压缩密钥。这就是为什么它总是会失败,因为输入密钥的长度 (65) 与压缩密钥的预期长度 (33) 不匹配。
请注意,函数 sharedSecret(forPublicKeyBase64:)
将在内部调用 sharedSecret(forPublicKey:)
。所以最终的解决方案是在将密钥传递给sharedSecret(forPublicKey:)
之前再次压缩密钥。您可以选择在头文件中公开 compressPublicKey
函数,或者使用以下解决方案更新 .m 文件中的函数。
原文:
// Prepare the public key
- (NSData*)sharedSecretForPublicKey: (NSData*)otherPublicKey {
[...]
uint8_t l_other_public[_bytes + 1];
if ([otherPublicKey length] != _bytes + 1) {
[NSException raise:@"Invalid Key" format:@"Public key %@ is invalid", otherPublicKey];
}
[...]
}
修复:
- (NSData*)sharedSecretForPublicKey: (NSData*)otherPublicKey {
NSData* compressedKey = [self compressPublicKey:otherPublicKey];
[...]
// Prepare the public key
uint8_t l_other_public[_bytes + 1];
if ([compressedKey length] != _bytes + 1) {
[NSException raise:@"Invalid Key" format:@"Public key %@ is invalid", compressedKey];
}
[compressedKey getBytes:&l_other_public length:[compressedKey length]];
[...]
}
终于找到解决方法了
从服务器收到 public 密钥后,我应该这样做:
private func getPublicKey(publicKey: String) -> String? {
if let publicKeyData = Data(base64Encoded: publicKey) {
var newKeyData = publicKeyData
newKeyData.insert(0x04, at: 0)
if let compressKeyData = curveCrypto?.compressPublicKey(newKeyData) {
return compressKeyData.base64EncodedString()
} else {
print("PUB KEY ERROR: compressKeyData")
return nil
}
} else {
print("PUB KEY ERROR: b64")
return nil
}
}
并且这个 public 密钥应该用于生成共享密钥。