Swift使用ECDH生成共享密钥时报公钥无效错误如何解决?
问题原因
你在生成本地公钥时主动移除了secp256r1非压缩公钥的标准前缀,而你调用的sharedSecret(forPublicKeyBase64:)方法要求传入的公钥必须带标准前缀,所以触发了无效公钥报错。
secp256r1的非压缩公钥标准格式为65字节:固定开头字节0x04 + 32字节X坐标 + 32字节Y坐标。你代码中let pub = Data(publicKey[1...publicKey.count-1])这行把开头的0x04前缀删除了,所以你发给服务器的是64字节的无前缀公钥,服务器返回给你的公钥也是同样去掉前缀的64字节格式,直接传给GMEllipticCurveCrypto的接口就会校验失败。
解决方法
在调用生成共享密钥的接口前,给服务器返回的公钥补上0x04前缀即可,修改后的generateSecret代码参考:
func generateSecret(withKey key: String) { guard let crypto = curveCrypto, let serverPubKeyData = Data(base64Encoded: key) else { return } // 补公钥前缀0x04 var fullPubKeyData = Data([0x04]) fullPubKeyData.append(serverPubKeyData) let fullPubKeyBase64 = fullPubKeyData.base64EncodedString() sharedKey = crypto.sharedSecret(forPublicKeyBase64: fullPubKeyBase64) }
额外注意点
- 你当前给服务器发的公钥已经去掉了前缀,只要服务器侧的解析逻辑是按64字节无前缀公钥处理的,就不需要调整发送逻辑,仅调整接收公钥的处理逻辑即可。
- 如果后续需要切换为压缩公钥格式,需要同步修改
compressedPublicKey属性,并且和服务器对齐压缩公钥的前缀规则(压缩公钥前缀为0x02或0x03,总长度33字节)。
内容的提问来源于stack exchange,提问作者strevg
相关产品推荐
相关产品推荐

