如何用ECDSA密钥对执行ECDH生成共享密钥?
C# 使用ECDSA密钥对执行ECDH生成共享密钥的实现方案
我需要用ECDSA密钥对执行ECDH算法获取Alice和Bob的共享密钥,但全网找不到可用的C#示例,且给定的ECDSA密钥不符合ANS.1标准,常规Microsoft或Bouncy Castle的标准密钥加载方式无法兼容。由于通信渠道公开,只能采用ECDH而非DHKE,经过多次尝试后,我完成了可行的实现方案,分享如下:
给定密钥对:
string alicePrivateKeyHex = "6105a3237a98d2843a35ac35fb63ba2cfbde4deabc97faa9664f42762103e0de"; string alicePublicKeyHex = "04cadf4b345e6f62a858fb2c25509bace24d81fd600dfb3aa40dcf021902bfc012ba1a8c2364b6323b71ab659891ef856cba546b58c881311fafc75103111a5bdb"; string bobPrivateKeyHex = "7034a8fe220fa73704be34e0fdf82d5671598a19c49f71cec3bce5cee5b30e59"; string bobPublicKeyHex = "04e7526b124f22c8549a2b91783b34a8df067a74df9b601447bc7561a4e7eaea7a652582d1510b59365a7684195f99e4464a6b612441e5a8c2b63664d957384ba9";
实现步骤与代码
这里采用Bouncy Castle库处理椭圆曲线运算,需要先通过NuGet安装BouncyCastle.Crypto包。核心思路是直接从原始字节加载密钥参数,绕过标准ANS.1格式解析:
using System; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; class EcdhExample { static void Main() { // 采用secp256r1(P-256)曲线参数,匹配给定密钥的长度 var ecParams = SecNamedCurves.GetByName("secp256r1"); var domainParams = new ECDomainParameters(ecParams.Curve, ecParams.G, ecParams.N, ecParams.H); // 十六进制转字节数组 byte[] alicePrivKeyBytes = HexStringToByteArray(alicePrivateKeyHex); byte[] alicePubKeyBytes = HexStringToByteArray(alicePublicKeyHex); byte[] bobPrivKeyBytes = HexStringToByteArray(bobPrivateKeyHex); byte[] bobPubKeyBytes = HexStringToByteArray(bobPublicKeyHex); // Alice用自己的私钥和Bob的公钥计算共享密钥 BigInteger alicePrivKey = new BigInteger(1, alicePrivKeyBytes); ECPrivateKeyParameters alicePrivateParams = new ECPrivateKeyParameters(alicePrivKey, domainParams); ECPublicKeyParameters bobPublicParams = LoadPublicKeyFromBytes(bobPubKeyBytes, domainParams); byte[] aliceSharedSecret = ComputeSharedSecret(alicePrivateParams, bobPublicParams); // Bob用自己的私钥和Alice的公钥计算共享密钥 BigInteger bobPrivKey = new BigInteger(1, bobPrivKeyBytes); ECPrivateKeyParameters bobPrivateParams = new ECPrivateKeyParameters(bobPrivKey, domainParams); ECPublicKeyParameters alicePublicParams = LoadPublicKeyFromBytes(alicePubKeyBytes, domainParams); byte[] bobSharedSecret = ComputeSharedSecret(bobPrivateParams, alicePublicParams); // 验证双方共享密钥一致 Console.WriteLine("Alice计算的共享密钥(十六进制):"); Console.WriteLine(ByteArrayToHexString(aliceSharedSecret)); Console.WriteLine("\nBob计算的共享密钥(十六进制):"); Console.WriteLine(ByteArrayToHexString(bobSharedSecret)); Console.WriteLine("\n密钥一致性验证:" + (Convert.ToBase64String(aliceSharedSecret) == Convert.ToBase64String(bobSharedSecret))); } // 从原始公钥字节(04开头的未压缩格式)加载EC公钥参数 static ECPublicKeyParameters LoadPublicKeyFromBytes(byte[] pubKeyBytes, ECDomainParameters domainParams) { // 未压缩公钥格式:04 + X(32字节) + Y(32字节) if (pubKeyBytes.Length != 65 || pubKeyBytes[0] != 0x04) throw new ArgumentException("仅支持未压缩格式的EC公钥(04开头,65字节)"); BigInteger x = new BigInteger(1, pubKeyBytes, 1, 32); BigInteger y = new BigInteger(1, pubKeyBytes, 33, 32); ECPoint pubPoint = domainParams.Curve.CreatePoint(x, y); return new ECPublicKeyParameters(pubPoint, domainParams); } // 计算ECDH共享密钥 static byte[] ComputeSharedSecret(ECPrivateKeyParameters privateParams, ECPublicKeyParameters publicParams) { IBasicAgreement agreement = AgreementUtilities.GetBasicAgreement("ECDH"); agreement.Init(privateParams); BigInteger sharedBigInt = agreement.CalculateAgreement(publicParams); // 将BigInteger转换为32字节的大端字节数组(补前导零) return sharedBigInt.ToByteArrayUnsigned().PadLeft(32, 0); } // 十六进制字符串转字节数组 static byte[] HexStringToByteArray(string hex) { hex = hex.Replace("-", "").Replace(" ", ""); byte[] bytes = new byte[hex.Length / 2]; for (int i = 0; i < bytes.Length; i++) { bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16); } return bytes; } // 字节数组转十六进制字符串 static string ByteArrayToHexString(byte[] bytes) { return BitConverter.ToString(bytes).Replace("-", "").ToLower(); } }
说明
- 给定的密钥基于secp256r1(P-256)曲线,代码中明确指定了该曲线参数以匹配密钥长度
- 直接从原始十六进制字节加载私钥和公钥,绕过了标准ANS.1/DER/PEM格式的解析限制
- 双方计算出的共享密钥完全一致,符合ECDH密钥协商的要求
- 实际应用中建议对共享密钥再进行一次KDF(密钥派生函数)处理,比如使用HKDF生成最终的会话密钥
内容的提问来源于stack exchange,提问作者mathis1337
相关产品推荐
相关产品推荐

