簡體   English   中英

swift 使用 ECDH 生成共享密鑰

[英]swift Generate shared key using ECDH

我正在嘗試加密發送到服務器的消息。 為此,我生成了公鑰和私鑰。 我將我的公鑰發送到服務器並從中接收它的公鑰。

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

*** 由於未捕獲的異常“無效密鑰”而終止應用程序,原因:“公鑰{長度 = 64,字節 = 0xace3000d e1483ed9 82d88432 9397c716 ... d64e0fe1 47920d9f } 無效”

我的公鑰和服務器密鑰的長度相同。

我做錯了什么?

我相信您正在使用ricmoo的 GEllipticCurveCrypto。

該框架在內部使用壓縮密鑰。 這就是為什么它總是會失敗,因為輸入密鑰(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]];
    [...]
}

最后我找到了解決方案。

從服務器收到公鑰后,我應該這樣做:

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

這個公鑰應該用於生成共享密鑰。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM