如何修正Crypto++ ECDH硬编码密钥实现以获取正确共享密钥
修正secp256r1曲线ECDH密钥交换代码的问题
问题根源
- 公钥格式不兼容:你提供的Party B公钥是64字节的原始x+y坐标,但Crypto++的ECDH公钥要求带非压缩标识前缀(0x04),总长度应为65字节。
- 私钥处理冗余:无需手动处理符号转换,
StringSource解码后的字节可直接赋值给SecByteBlock。 - 共享密钥输出错误:用
Integer解码会丢失前导零或导致格式异常,应直接将共享密钥的字节转成十六进制输出。
修正后的代码
#include <iostream> #include <string> #include "cryptopp/eccrypto.h" #include "cryptopp/secblock.h" #include "cryptopp/oids.h" #include "cryptopp/hex.h" #include "cryptopp/filters.h" using namespace CryptoPP; int main() { const OID CURVE = ASN1::secp256r1(); ECDH<ECP>::Domain dh(CURVE); // Party A私钥(32字节十六进制) const std::string privatekeyA = "e8586d5fa27ffb6a37817c171c94189ad20d8fcf29fa58ba0e6cbe4cf2bb1079"; // Party B公钥:在原始64字节坐标前添加0x04前缀(非压缩标识) const std::string publickeyB = "044f0609f35a0be01caa1287862680b803ea50fb66af2ad65e990aa4a8944c6191ac0d13d98612e12ba1d9afa86f997aab2827a0cee43bf963e8e995eb95df2fb33"; SecByteBlock privA(dh.PrivateKeyLength()); SecByteBlock pubB(dh.PublicKeyLength()); // 解码私钥到SecByteBlock StringSource(privatekeyA, true, new HexDecoder( new ArraySink(privA.begin(), privA.size()) ) ); // 解码公钥到SecByteBlock StringSource(publickeyB, true, new HexDecoder( new ArraySink(pubB.begin(), pubB.size()) ) ); // 执行ECDH密钥协商 SecByteBlock sharedSecret(dh.AgreedValueLength()); if (!dh.Agree(sharedSecret, privA, pubB)) { std::cerr << "密钥协商失败!" << std::endl; return 1; } // 将共享密钥转成十六进制字符串输出 std::string sharedHex; StringSource(sharedSecret.begin(), sharedSecret.size(), true, new HexEncoder( new StringSink(sharedHex) ) ); std::cout << "共享密钥:" << sharedHex << std::endl; return 0; }
核心修改说明
- 给Party B的公钥添加
04前缀,匹配CryptoPP对非压缩椭圆曲线公钥的格式要求。 - 使用
ArraySink直接将解码后的字节写入SecByteBlock,移除冗余的手动字节转换逻辑。 - 用
HexEncoder直接将共享密钥的字节数组转为十六进制字符串,避免Integer解码带来的格式偏差。
内容的提问来源于stack exchange,提问作者janhere3
相关产品推荐
相关产品推荐

