iOS Swift中如何利用服务器十六进制ECDH公钥生成共享密钥
解决服务器十六进制EC公钥转SecKey并生成共享密钥问题
步骤1:将十六进制公钥转为Data
首先把服务器返回的十六进制字符串转成二进制Data,注意:如果服务器返回的公钥是仅包含x、y坐标拼接的64字节十六进制(无04前缀),需要先补上04前缀——Apple的SecKey要求EC公钥遵循X9.63未压缩格式(开头为04,后续接32字节x坐标+32字节y坐标,共65字节)。
// 十六进制转Data工具方法 func hexStringToData(_ hexString: String) -> Data? { let cleanedStr = hexString.trimmingCharacters(in: .whitespacesAndNewlines) var data = Data(capacity: cleanedStr.count / 2) var index = cleanedStr.startIndex while index < cleanedStr.endIndex { let nextIndex = cleanedStr.index(index, offsetBy: 2) guard let byte = UInt8(cleanedStr[index..<nextIndex], radix: 16) else { return nil } data.append(byte) index = nextIndex } // 补04前缀(如果是64字节的坐标拼接数据) if data.count == 64 { var prefixedData = Data([0x04]) prefixedData.append(data) return prefixedData } return data }
步骤2:构造公钥属性字典
属性需和你本地生成密钥对时的参数完全匹配,保证密钥类型、大小、曲线一致:
let publicKeyAttrs: [String: Any] = [ kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeyClass as String: kSecAttrKeyClassPublic, kSecAttrKeySizeInBits as String: 256, kSecAttrIsPermanent as String: false ]
步骤3:生成SecKey实例
用SecKeyCreateWithData将二进制Data转换为SecKey对象:
var error: Unmanaged<CFError>? // serverHexPublicKey为服务器返回的十六进制公钥字符串 guard let serverPubKeyData = hexStringToData(serverHexPublicKey), let serverPublicKey = SecKeyCreateWithData(serverPubKeyData as CFData, publicKeyAttrs as CFDictionary, &error) else { if let err = error?.takeRetainedValue() { print("公钥转换失败:\(err.localizedDescription)") } return }
步骤4:生成共享密钥
用本地私钥和转换后的服务器公钥执行ECDH密钥交换,逻辑和你本地测试的一致:
let algorithm: SecKeyAlgorithm = .ecdhKeyExchangeStandardX963SHA256 let exchangeParams: [String: Any] = [ SecKeyKeyExchangeParameter.requestedSize.rawValue as String: 32 ] guard let sharedSecret = SecKeyCopyKeyExchangeResult(localPrivateKey, algorithm, serverPublicKey, exchangeParams as CFDictionary, &error) as Data? else { if let err = error?.takeRetainedValue() { print("共享密钥生成失败:\(err.localizedDescription)") } return } print("服务器端共享密钥:\(sharedSecret.base64EncodedString())")
常见排查点
- 检查十六进制字符串是否有多余空格、特殊字符,确保格式正确。
- 确认服务器公钥的曲线和本地一致(你用的是P-256曲线,对应256位密钥),若服务器用P-384等其他曲线,需修改
kSecAttrKeySizeInBits为对应值。 - 若服务器返回的是压缩格式公钥(33字节,开头为
02或03),需先自行解压为未压缩格式(Apple SecKey不直接支持压缩EC公钥)。
内容的提问来源于stack exchange,提问作者Shreedharshan Msd
相关产品推荐
相关产品推荐

