如何在Crypto++中从硬编码字符串加载RSA私钥?
问题:硬编码DER格式RSA私钥到Crypto++程序时触发BERDecodeErr异常
背景
通过以下步骤生成并转换RSA私钥:
- 用OpenSSL生成PEM格式私钥:
openssl genrsa -out privatKey.pem 2048 - 转换为PKCS#8 DER格式以适配Crypto++加载:
openssl pkcs8 -in privatKey.pem -out privatKey.der -topk8 -nocrypt -outform der
从文件加载该DER密钥的代码可正常运行:
ByteQueue queue; FileSource file("privatKey.der", true); file.TransferTo(queue); queue.MessageEnd(); RSA::PrivateKey rsaPrivate; rsaPrivate.Load(queue);
问题场景
尝试将密钥硬编码到代码中:
- 用
xxd -p privatKey.der导出十六进制字符串,赋值给std::string privKeyStr - 用
StringSource加载该字符串时,抛出CryptoPP::BERDecodeErr异常:
std::string privKeyStr = "308204bd020100300d06092a864886f70d0101010500048204a7308204a3" "0201000282010100ba077fcaf8908c0b9bfef58f4493c93affb6ca7b2947" // 省略剩余十六进制内容 "64c1af4ce4857b1cba7b21d7d59a7e5ab9"; ByteQueue queue; StringSource str(privKeyStr, true); str.TransferTo(queue); queue.MessageEnd(); RSA::PrivateKey rsaPrivate; rsaPrivate.Load(queue); // 此处抛出BERDecodeErr
原因分析
xxd -p输出的是ASCII格式的十六进制字符序列(比如字符'3'、'0'对应的ASCII值是0x33、0x30),而RSA::PrivateKey.Load()需要的是DER格式的原始二进制字节。直接传递ASCII字符串会导致解码时无法识别BER格式的结构,从而抛出异常。
解决方案
方案1:用Crypto++ HexDecoder解码十六进制字符串
通过HexDecoder将ASCII十六进制字符串转换为二进制字节流,再传入ByteQueue:
#include <cryptopp/hex.h> #include <cryptopp/rsa.h> #include <cryptopp/queue.h> #include <cryptopp/strings.h> std::string privKeyStr = "308204bd020100300d06092a864886f70d0101010500048204a7308204a3" "0201000282010100ba077fcaf8908c0b9bfef58f4493c93affb6ca7b2947" // 省略剩余十六进制内容 "64c1af4ce4857b1cba7b21d7d59a7e5ab9"; ByteQueue queue; // 解码十六进制字符串到二进制队列 StringSource str(privKeyStr, true, new HexDecoder(new Redirector(queue))); queue.MessageEnd(); RSA::PrivateKey rsaPrivate; rsaPrivate.Load(queue); // 正常加载
方案2:直接生成C++二进制字节数组(推荐)
使用xxd -i命令直接生成可嵌入代码的二进制字节数组,避免运行时解码开销:
xxd -i privatKey.der > privkey.h
生成的privkey.h内容示例:
unsigned char privatKey_der[] = { 0x30, 0x82, 0x04, 0xbd, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, // 剩余字节由xxd自动生成 }; unsigned int privatKey_der_len = 1213; // 实际长度与密钥匹配
加载该字节数组的代码:
#include "privkey.h" #include <cryptopp/rsa.h> #include <cryptopp/queue.h> #include <cryptopp/arrays.h> ByteQueue queue; ArraySource arr(privatKey_der, privatKey_der_len, true, new Redirector(queue)); queue.MessageEnd(); RSA::PrivateKey rsaPrivate; rsaPrivate.Load(queue); // 正常加载
内容的提问来源于stack exchange,提问作者ibse
相关产品推荐
相关产品推荐

