簡體   English   中英

使用 swift 使用公鑰和私鑰創建共享密鑰

[英]Creating shared secret using public and private keys using swift

我正在嘗試將一個字節序列的ephemeralKey轉換為一個橢圓曲線公鑰,然后用它來創建一個使用我的私鑰的共享密鑰。

我知道如何在 python(下面的代碼)中執行此操作。 但是我在 Swift 找不到方法。我的 Swift 代碼也在下面復制,但它不正確。 你看到我的 Swift 代碼有問題了嗎?

我的 python 代碼:

from cryptography.hazmat.primitives.asymmetric import ec

privateKey = ec.generate_private_key(ec.SECP256R1())
devicePublicKey = ec.EllipticCurvePublicKey.from_encoded_point(ec.SECP256R1(), ephemeralKey)
sharedKey = privateKey.exchange(ec.ECDH(), devicePublicKey)

我的 Swift 代碼:


let privateKeyParams: [String: Any] = [
    kSecAttrKeyClass as String: kSecAttrKeyClassPrivate,
    kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
    kSecAttrKeySizeInBits as String: 256
            ]
var error: Unmanaged<CFError>?
let privateKey = SecKeyCreateRandomKey(privateKeyParams as CFDictionary, &error)
let attributes: [String:Any] =
        [
            kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
            kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
            kSecAttrKeySizeInBits as String: 256,
        ]
let devicePublicKey = SecKeyCreateWithData(ephemeralKey as CFData, attributes as CFDictionary, nil)!
let sharedKey = ecdhSecretCalculation(publicKey: devicePublicKey, privateKey: privateKey) 

func ecdhSecretCalculation(publicKey: SecKey, privateKey: SecKey) -> Data? {
        var error: Unmanaged<CFError>?
        
        let keyPairAttr:[String : Any] = [
            kSecAttrKeySizeInBits as String: 256,
            SecKeyKeyExchangeParameter.requestedSize.rawValue as String: 32,
            kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
            kSecPrivateKeyAttrs as String: [kSecAttrIsPermanent as String: false],
            kSecPublicKeyAttrs as String:[kSecAttrIsPermanent as String: false]
        ]
        
        let algorithm:SecKeyAlgorithm = .ecdhKeyExchangeStandardX963SHA256
        
        let shared = SecKeyCopyKeyExchangeResult(privateKey, algorithm, publicKey, keyPairAttr as CFDictionary, &error) as Data?
        
        return shared
}

不同共享密鑰的原因是ecdhKeyExchangeStandardX963SHA256在發布的 Swift 代碼中應用。 相反,必須應用ecdhKeyExchangeStandard

另外,請記住 Swift 代碼中的SecKeyCreateWithData()期望私鑰是未壓縮的公鑰 ( 0x04|x|y ) 和原始私鑰: 0x04|x|y|private的串聯,而在Python 代碼只指定了原始私鑰(這只是為了完整性,因為發布的代碼沒有顯示私鑰是如何導入的)。

如果考慮到這一點,則兩個代碼都提供相同的共享秘密。


測試:

Python:

from cryptography.hazmat.primitives.asymmetric import ec
import base64

ephemeralKey = base64.b64decode("BK/Rckcy/PFSkdMCIYg6/CRTk3eSv4VQ2+7sNFQ8TjO1aqK5Wmb+UgjDPQ5cB1QGccATrtmgPDRnPzR5JCMPs/M=")
devicePublicKey = ec.EllipticCurvePublicKey.from_encoded_point(ec.SECP256R1(), ephemeralKey)

privateKeyRaw = base64.b64decode("v5PriRLFXqqILYFZkX2LWEbUQ/y/NCZXD6il5S6KPus=")
privateKey = ec.derive_private_key(int.from_bytes(privateKeyRaw, 'big'), ec.SECP256R1())

sharedKey = privateKey.exchange(ec.ECDH(), devicePublicKey)
print(base64.b64encode(sharedKey)) # 8bOrCLEe1eCciEDbq710xbSXQnKzvSHnVjnXnhpJImE=

Swift:

import Foundation

let keyStringPub = "BK/Rckcy/PFSkdMCIYg6/CRTk3eSv4VQ2+7sNFQ8TjO1aqK5Wmb+UgjDPQ5cB1QGccATrtmgPDRnPzR5JCMPs/M="
let ephemeralKey = Data(base64Encoded: keyStringPub)!
let devicePublicKey = SecKeyCreateWithData(ephemeralKey as CFData, [kSecAttrKeyClass as String: kSecAttrKeyClassPublic, kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeySizeInBits as String: 256] as CFDictionary, nil)!

let keyStringPriv = "BK/Rckcy/PFSkdMCIYg6/CRTk3eSv4VQ2+7sNFQ8TjO1aqK5Wmb+UgjDPQ5cB1QGccATrtmgPDRnPzR5JCMPs/O/k+uJEsVeqogtgVmRfYtYRtRD/L80JlcPqKXlLoo+6w=="
let privateKeyRaw = Data(base64Encoded: keyStringPriv)!
let privateKey = SecKeyCreateWithData(privateKeyRaw as CFData, [kSecAttrKeyClass as String: kSecAttrKeyClassPrivate, kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeySizeInBits as String: 256,] as CFDictionary, nil)!

let sharedKey = ecdhSecretCalculation(publicKey: devicePublicKey, privateKey: privateKey) 
let sharedKeyB64 = sharedKey!.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
print(sharedKeyB64) // 8bOrCLEe1eCciEDbq710xbSXQnKzvSHnVjnXnhpJImE=

func ecdhSecretCalculation(publicKey: SecKey, privateKey: SecKey) -> Data? {
        var error: Unmanaged<CFError>?        
        let keyPairAttr:[String : Any] = [
            kSecAttrKeySizeInBits as String: 256,
            SecKeyKeyExchangeParameter.requestedSize.rawValue as String: 32,
            kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
            kSecPrivateKeyAttrs as String: [kSecAttrIsPermanent as String: false],
            kSecPublicKeyAttrs as String:[kSecAttrIsPermanent as String: false]
        ]        
        let algorithm:SecKeyAlgorithm = .ecdhKeyExchangeStandard // Fix!
        let shared = SecKeyCopyKeyExchangeResult(privateKey, algorithm, publicKey, keyPairAttr as CFDictionary, &error) as Data?
        return shared
}

兩種代碼都提供相同的共享秘密。


如果在 Swift 代碼中使用了ecdhKeyExchangeStandardX963SHA256算法,則共享密鑰會額外使用ANSI-X9.63-KDF進行處理。 Cryptography 庫還提供了這個X963KDF

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.x963kdf import X963KDF
import base64

xkdf = X963KDF(
    algorithm=hashes.SHA256(),
    length=32,
    sharedinfo=None,
)
key = xkdf.derive(sharedKey)
print(base64.b64encode(key)) # ULQCW4bsStNQGg/avnlqaNALpAy2Z42SBZN97Qlnqa0=

對於之后通常使用 KDF 的原因,請參見此處 請注意,X9.63-KDF 只是一種可能性,還有其他可能性,請參見此處

暫無
暫無

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

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