提问者:小点点

椭圆曲线Diffie Hellman in ios/swift


iOS公开密钥生成和使用ECDH导出密钥的API吗?

据我所知,苹果正在内部使用它(特别是x25519),但我没有看到它被普通加密或其他方式公开为公共API。

谢谢,

Z


共3个答案

匿名用户

使用Xcode 8.3.3在游乐场中完成,使用EC为Alice、Bob生成私钥/公钥,然后使用Alice的私钥和Bob的公钥计算Alice的共享秘密,使用Bob的私钥和Alice的公钥为Bob共享秘密,最后断言它们是相等的。

import Security
import UIKit

let attributes: [String: Any] =
    [kSecAttrKeySizeInBits as String:      256,
     kSecAttrKeyType as String: kSecAttrKeyTypeEC,
     kSecPrivateKeyAttrs as String:
        [kSecAttrIsPermanent as String:    false]
]

var error: Unmanaged<CFError>?
if #available(iOS 10.0, *) {
    // generate a key for alice
    guard let privateKey1 = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
        throw error!.takeRetainedValue() as Error
    }
    let publicKey1 = SecKeyCopyPublicKey(privateKey1)

    // generate a key for bob
    guard let privateKey2 = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
        throw error!.takeRetainedValue() as Error
    }
    let publicKey2 = SecKeyCopyPublicKey(privateKey2)

    let dict: [String: Any] = [:]

    // alice is calculating the shared secret
    guard let shared1 = SecKeyCopyKeyExchangeResult(privateKey1, SecKeyAlgorithm.ecdhKeyExchangeStandardX963SHA256, publicKey2!, dict as     CFDictionary, &error) else {
        throw error!.takeRetainedValue() as Error
    }

    // bob is calculating the shared secret
    guard let shared2 = SecKeyCopyKeyExchangeResult(privateKey2, SecKeyAlgorithm.ecdhKeyExchangeStandardX963SHA256, publicKey1!, dict as CFDictionary, &error) else {
        throw error!.takeRetainedValue() as Error
    }

    print(shared1==shared2)


} else {
    // Fallback on earlier versions
    print("unsupported")
}

谢谢@Mats给我正确的方向

匿名用户

这是swift 5的最新代码和参数更改。

import Security
import UIKit

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 = SecKeyAlgorithm.ecdhKeyExchangeStandardX963SHA256//ecdhKeyExchangeStandardX963SHA256

do {
    guard let privateKey = SecKeyCreateRandomKey(keyPairAttr as CFDictionary, &error) else {
        throw error!.takeRetainedValue() as Error
    }
    let publicKey = SecKeyCopyPublicKey(privateKey)
    print("public ky1: \(String(describing: publicKey)),\n private key: \(privateKey)\n\n")



    guard let privateKey2 = SecKeyCreateRandomKey(keyPairAttr as CFDictionary, &error) else {
        throw error!.takeRetainedValue() as Error
    }
    let publicKey2 = SecKeyCopyPublicKey(privateKey2)
    print("public ky2: \(String(describing: publicKey2)),\n private key2: \(privateKey2)\n\n")



    let shared:CFData? = SecKeyCopyKeyExchangeResult(privateKey, algorithm, publicKey2!, keyPairAttr as CFDictionary, &error)
    let sharedData:Data = shared! as Data
    print("shared Secret key: \(sharedData.hexEncodedString())\n\n")

    let shared2:CFData? = SecKeyCopyKeyExchangeResult(privateKey2, algorithm, publicKey!, keyPairAttr as CFDictionary, &error)
    let sharedData2:Data = shared2! as Data
    print("shared Secret key 2: \(sharedData2.hexEncodedString())\n\n")

    // shared secret key and shared secret key 2 should be same

} catch let error as NSError {
    print("error: \(error)")
} catch  {
    print("unknown error")
}

extension Data {
    struct HexEncodingOptions: OptionSet {
        let rawValue: Int
        static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
    }

    func hexEncodedString(options: HexEncodingOptions = []) -> String {
        let format = options.contains(.upperCase) ? "%02hhX" : "%02hhx"
        return self.map { String(format: format, $0) }.joined()
    }
}

匿名用户

Circa-2020和iOS13。在下面的Zohar代码片段中,在尝试获取共享机密之前,还要在字典中指定密钥大小。

let dict: [String: Any] = [SecKeyKeyExchangeParameter.requestedSize.rawValue as String: 32]

否则这样说会有错误。

kSecKeyKeyExchangeParameterRequestedSize丢失