C++ 在Crypto+中加载PEM编码的RSA私钥+;

C++ 在Crypto+中加载PEM编码的RSA私钥+;,c++,encryption,cryptography,rsa,crypto++,C++,Encryption,Cryptography,Rsa,Crypto++,通常情况下,用户将拥有PEM编码的RSA私钥。Crypto++要求以DER格式加载这些密钥。我一直要求人们事先使用openssl手动将其PEM文件转换为DER,如下所示: openssl pkcs8 -in in_file.pem -out out_file.der -topk8 -nocrypt -outform der 这很好,但有些人不知道怎么做,也不想这么做。所以我想在程序中自动将PEM文件转换为DER文件 它是否像从PEM中剥离“----开始证书------”和“----结束证书--

通常情况下,用户将拥有PEM编码的RSA私钥。Crypto++要求以DER格式加载这些密钥。我一直要求人们事先使用openssl手动将其PEM文件转换为DER,如下所示:

openssl pkcs8 -in in_file.pem -out out_file.der -topk8 -nocrypt -outform der
这很好,但有些人不知道怎么做,也不想这么做。所以我想在程序中自动将PEM文件转换为DER文件

它是否像从PEM中剥离“----开始证书------”和“----结束证书------”一样简单,还是还需要其他转换?有人告诉我,在这些标记之间,这只是b64编码的DER。下面的一些代码演示了这个问题:

// load the private key
CryptoPP::RSA::PrivateKey PK;
CryptoPP::ByteQueue bytes;

try
{
    CryptoPP::FileSource File( rsa.c_str(), true, new CryptoPP::Base64Decoder() );
    File.TransferTo( bytes );
    bytes.MessageEnd();

    // This line Causes BERDecodeError when a PEM encoded file is used
    PK.Load( bytes );
}

catch ( CryptoPP::BERDecodeErr )
{
    // Convert PEM to DER and try to load the key again
}

我希望避免对openssl进行系统调用,完全用Crypto++进行转换,这样用户就可以提供格式和“正常工作”的东西。谢谢你的建议。

是的,这是一个用Base64编码的DER流。但是请注意,除了将开始标记和结束标记分条外,对于RSA密钥格式,还需要将可能插入开始标记和编码数据之间的任何标志分条。只有剩余部分可以成功地进行Base64解码。似乎您将完整的证书文件提供给了解码器,需要修复。

我知道这是一个老问题,但其他人可能会发现这很有用。剥去标记后,剩下的是“内部”关键材质。根据,您可以使用
BERDecodePrivateKey
加载此文件。因此,要加载一个标记已被剥离的openssl密钥,您可以执行以下操作

bool LoadKey(RandomNumberGenerator& rng, const std::string& file, 
    RSA::PrivateKey& key)
{
    ByteQueue q;
    FileSource KeyFile(file.c_str(), true, new Base64Decoder);
    KeyFile.TransferTo(q);
    key.BERDecodePrivateKey(q,false,0); // last 2 params unused
    return key.Validate(rng, 2);
}
。。。我想在程序中自动将PEM文件转换为DER文件

2014年7月,为Crypto++库提供了。PEM包是消息加密的部分实现,允许您读取和写入PEM编码的密钥和参数,包括加密的私钥。附加文件包括对RSA、DSA、EC、ECDSA密钥和Diffie-Hellman参数的支持

它是库的附加组件,而不是库本身的一部分。您下载一个ZIP文件并向库中添加五个源文件。然后构建库(Crypto++会自动拾取它们)。ZIP包含五个附加的源文件,一个使用OpenSSL创建测试密钥的脚本,一个C++程序,用于测试读写键,以及一个脚本,用OpenSSL。 以下是您将如何使用它:

CryptoPP::RSA::PrivateKey pk;
CryptoPP::FileSource file("<rsa-key-file.pem>", true);

CryptoPP::PEM_Load(file, pk);

CryptoPP::AutoSeededRandomPool prng;
bool = pk.Validate(prng, 3);
if (! valid)
    throw ...
还有一个
PEM_Save
,因此您可以直接从Crypto++编写密钥。例如:

// Generate it or load it from somewhere
CryptoPP::RSA::PrivateKey pk = ...; 
CryptoPP::FileSink file("<rsa-key-file.pem>", true);

CryptoPP::PEM_Save(file, pk);

PEM_Load
不需要算法,因为其编码在封装的报头中
PEM_Save
需要一个算法,因为没有默认算法。

我很感激你的回答。我可以通过对openssl的std::系统调用来进行转换。这很好,但它是一个黑客。我想完全用Crypto++完成从PEM到DER的转换。我已经开始了一项赏金计划。如果可以完全在密码+++和标准C++中完成,那么我会奖励任何能提供工作源代码的人。你已经得到正确答案,你应该自己编写代码。Base 64和一些字符串处理应该不会那么困难。@owlstead-我可以做这些事情。关于在BEGIN标记之后剥离RSA标志的部分我不清楚。我经常使用Crypto++编写代码,以便能够处理它,但我想看到的是一个具体的例子。我还没有在其他地方找到任何关于这个的文档。希望是这里的人干的。我还应该补充一点,我不生成这些PEM,对它们的生成方式也没有任何控制或输入。问题是你要求为你创建代码,这不是这个网站的目的。在问了一个不需要生成任何代码的问题后,您就可以这样做了。您是在寻找内存中的解码器,还是磁盘上的解码器也很好?@OrgnlDave-任何使用Crypto++的示例都可以。@01100110-Crypto++现在作为一个附加组件提供了此支持。请参见Crypto++wiki上的。
// Generate it or load it from somewhere
CryptoPP::RSA::PrivateKey pk = ...; 
CryptoPP::FileSink file("<rsa-key-file.pem>", true);

CryptoPP::PEM_Save(file, pk);
// Generate it or load it from somewhere
CryptoPP::RSA::PrivateKey pk = ...; 
CryptoPP::FileSink file("<rsa-key-file.pem>", true);

std::string pass = "<super secret password>";
CryptoPP::PEM_Save(file, pk, "AES-128-CBC", pass.data(), pass.size());