简体   繁体   English

swift 使用 ECDH 生成共享密钥

[英]swift Generate shared key using ECDH

I am trying to encrypt a message to the server.我正在尝试加密发送到服务器的消息。 To do this, I generate a public and private key.为此,我生成了公钥和私钥。 I send my public key to the server and receive its public key from it.我将我的公钥发送到服务器并从中接收它的公钥。

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
        }
    }
}

Upon receipt, I try to generate a shared key to encrypt the data.收到后,我尝试生成一个共享密钥来加密数据。

func generateSecret(withKey key: String) {
    guard let crypto = curveCrypto else {
        return
    }
    print("generateSecret \(key)")
    sharedKey = crypto.sharedSecret(forPublicKeyBase64: key)
}

But I get the error in line (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' *** 由于未捕获的异常“无效密钥”而终止应用程序,原因:“公钥{长度 = 64,字节 = 0xace3000d e1483ed9 82d88432 9397c716 ... d64e0fe1 47920d9f } 无效”

My public key and server key are the same length.我的公钥和服务器密钥的长度相同。

What is I doing wrong?我做错了什么?

I believe you are using GMEllipticCurveCrypto by ricmoo.我相信您正在使用ricmoo的 GEllipticCurveCrypto。

This framework use compressed keys internally.该框架在内部使用压缩密钥。 Which is why it will always fail as the length of the input key(65) doesn't match the expected length of compressed key(33).这就是为什么它总是会失败,因为输入密钥(65)的长度与压缩密钥(33)的预期长度不匹配。

Note that the function sharedSecret(forPublicKeyBase64:) will call sharedSecret(forPublicKey:) internally.请注意,函数sharedSecret(forPublicKeyBase64:)将在内部调用sharedSecret(forPublicKey:) So the final solution is to compress the key again before passing it to sharedSecret(forPublicKey:) .所以最终的解决方案是在将密钥传递给sharedSecret(forPublicKey:)之前再次压缩密钥。 You can choose to expose compressPublicKey function in header file or use update the function in .m file with the solution below.您可以选择在头文件中公开compressPublicKey函数或使用以下解决方案更新 .m 文件中的函数。

Original:原来的:

// 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];
    }
    [...]
}

Fix:使固定:

- (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]];
    [...]
}

Finally I have found the solution.最后我找到了解决方案。

After receiving public key from server I should do this:从服务器收到公钥后,我应该这样做:

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
    }
}

And this public key should be used for generation shared key.这个公钥应该用于生成共享密钥。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM