基于Diffie-Hellman与Crypto++生成密钥异常:同参数却生成不同密钥
Crypto++ Diffie-Hellman 问题修正
你的代码存在多处关键错误,导致公私钥生成不符合DH协议预期,以下是问题分析和修正方案:
核心错误点
- 私钥生成逻辑错误:你为Alice和Bob调用
PrimeAndGenerator::Generate()生成新的素数对,然后把生成元当作私钥a/b。DH的私钥应该是**[1, p-2]范围内的随机整数**,不是新的生成元。 - 手动幂运算实现错误:自定义的
my_pow未在每一步取模,中间结果会异常庞大,效率极低且易出错。Crypto++内置a_exp_b_mod_c函数可直接完成模幂计算,无需手动实现。 - DH类使用错误:你将手动计算的共享密钥传入DH构造函数,这完全不符合API要求。DH类的构造参数是共享素数
p、生成元g,以及可选的私钥长度;且手动计算共享密钥与使用DH类是两种互斥的实现方式,无需重复操作。 - SecByteBlock输出错误:直接打印
SecByteBlock会输出乱码或内存地址,需通过Hex编码器转换为可读字符串。
修正后的代码
#include <iostream> #include <string> #include <cryptopp/cryptlib.h> #include <cryptopp/dh.h> #include <cryptopp/osrng.h> #include <cryptopp/integer.h> #include <cryptopp/hex.h> #include <cryptopp/secblock.h> using namespace std; using namespace CryptoPP; int main(int argc, char* argv[]) { std::cout << std::hex; // 生成共享的DH参数:素数p,生成元g(对应原代码的q) AutoSeededRandomPool rnd; PrimeAndGenerator pg; // Generate(1, 随机数生成器, 素数长度, 子素数长度) pg.Generate(1, rnd, 512, 511); const Integer p = pg.Prime(); const Integer g = pg.Generator(); cout << "共享素数p: " << p << endl; cout << "共享生成元g: " << g << endl; // ------------------------------ // Alice的密钥生成 // ------------------------------ AutoSeededRandomPool prngA; // 生成Alice的私钥:随机整数,范围[1, p-2] Integer a(rnd, Integer(1), p-2); // 计算Alice的公钥: g^a mod p Integer aPub = a_exp_b_mod_c(g, a, p); // ------------------------------ // Bob的密钥生成 // ------------------------------ AutoSeededRandomPool prngB; // 生成Bob的私钥:随机整数,范围[1, p-2] Integer b(rnd, Integer(1), p-2); // 计算Bob的公钥: g^b mod p Integer bPub = a_exp_b_mod_c(g, b, p); cout << "\nAlice私钥a: " << a << endl; cout << "Alice公钥aPub: " << aPub << endl; cout << "\nBob私钥b: " << b << endl; cout << "Bob公钥bPub: " << bPub << endl; // ------------------------------ // 计算共享密钥 // ------------------------------ // Alice用Bob的公钥计算共享密钥: bPub^a mod p = g^(ab) mod p Integer aliceShared = a_exp_b_mod_c(bPub, a, p); // Bob用Alice的公钥计算共享密钥: aPub^b mod p = g^(ab) mod p Integer bobShared = a_exp_b_mod_c(aPub, b, p); cout << "\nAlice计算的共享密钥: " << aliceShared << endl; cout << "Bob计算的共享密钥: " << bobShared << endl; if (aliceShared == bobShared) cout << "\n共享密钥一致!" << endl; // ------------------------------ // (可选)用Crypto++ DH类验证流程 // ------------------------------ cout << "\n--- 使用Crypto++ DH类生成密钥对 ---" << endl; // 初始化DH对象(使用共享参数p和g) DH dh(p, g); // Alice的DH密钥对 SecByteBlock alicePriv(dh.PrivateKeyLength()), alicePub(dh.PublicKeyLength()); dh.GenerateKeyPair(rnd, alicePriv, alicePub); // 转换为Hex字符串输出 string alicePrivHex, alicePubHex; StringSource(alicePriv, alicePriv.size(), true, new HexEncoder(new StringSink(alicePrivHex))); StringSource(alicePub, alicePub.size(), true, new HexEncoder(new StringSink(alicePubHex))); cout << "Alice DH私钥(Hex): " << alicePrivHex << endl; cout << "Alice DH公钥(Hex): " << alicePubHex << endl; // Bob的DH密钥对 SecByteBlock bobPriv(dh.PrivateKeyLength()), bobPub(dh.PublicKeyLength()); dh.GenerateKeyPair(rnd, bobPriv, bobPub); string bobPrivHex, bobPubHex; StringSource(bobPriv, bobPriv.size(), true, new HexEncoder(new StringSink(bobPrivHex))); StringSource(bobPub, bobPub.size(), true, new HexEncoder(new StringSink(bobPubHex))); cout << "\nBob DH私钥(Hex): " << bobPrivHex << endl; cout << "Bob DH公钥(Hex): " << bobPubHex << endl; // 用DH类计算共享密钥 SecByteBlock aliceDHShared(dh.AgreedValueLength()); dh.Agree(aliceDHShared, alicePriv, bobPub); SecByteBlock bobDHShared(dh.AgreedValueLength()); dh.Agree(bobDHShared, bobPriv, alicePub); string aliceDHSharedHex, bobDHSharedHex; StringSource(aliceDHShared, aliceDHShared.size(), true, new HexEncoder(new StringSink(aliceDHSharedHex))); StringSource(bobDHShared, bobDHShared.size(), true, new HexEncoder(new StringSink(bobDHSharedHex))); cout << "\nAlice DH共享密钥(Hex): " << aliceDHSharedHex << endl; cout << "Bob DH共享密钥(Hex): " << bobDHSharedHex << endl; if (aliceDHShared == bobDHShared) cout << "\nDH类计算的共享密钥一致!" << endl; return 0; }
关键修正说明
- 私钥生成:直接用
Integer的随机构造函数生成符合范围的私钥,不再错误使用PrimeAndGenerator。 - 模幂计算:使用Crypto++内置的
a_exp_b_mod_c函数,高效且正确完成模幂运算。 - DH类使用:正确初始化DH对象,调用
GenerateKeyPair生成密钥对,用Agree方法计算共享密钥。 - 输出优化:通过
HexEncoder将SecByteBlock转换为可读的十六进制字符串,避免乱码。
内容的提问来源于stack exchange,提问作者zegar zegar
相关产品推荐
相关产品推荐

