2012-03-22 145 views
12

通常,用户将拥有PEM编码的RSA私钥。 Crypto ++要求这些密钥以DER格式加载。我一直在问的人手动转换他们的PEM文件事先DER使用OpenSSL的是这样的:在加密++中加载PEM编码的私有RSA密钥

openssl pkcs8 -in in_file.pem -out out_file.der -topk8 -nocrypt -outform der 

这工作正常,但有些人不明白该怎么做,也不做他们想做的。所以我想在程序中自动将PEM文件转换为DER文件。

它是否像PEM中的“----- BEGIN CERTIFICATE -----”和“----- END CERTIFICATE -----”一样简单,或者是其他需要的转换好?我被告知在这些标记之间它只是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和执行转换完全加密+,这样可以为用户提供两种格式,事情“只是工作”。感谢您的任何建议。

+0

您是在寻找内存中的解码器,还是在磁盘上的解码器? – 2012-03-25 18:49:36

+0

@OrgnlDave - 任何使用Crypto ++的例子都可以。 – 01100110 2012-03-25 21:01:15

+0

@ 01100110 - Crypto ++现在拥有这种支持作为附加组件。请参阅Crypto ++ wiki上的[PEM Pack](http://www.cryptopp.com/wiki/PEM_Pack)。 – jww 2014-08-24 22:19:29

回答

7

是的,这是一个用Base64编码的DER流。请注意,除了对BEGIN和END标记进行条带化之外,如果使用RSA密钥格式,还需要去除可能在BEGIN标记和编码数据之间插入的所有标记。只有剩余部分可以成功Base64解码。您似乎将完整的证书文件提供给解码器,需要修复。

+0

我很欣赏答案。我可以用std :: system调用openssl进行转换。这工作正常,但它是一个黑客。我想完全用Crypto ++来完成从PEM到DER的转换。 – 01100110 2012-03-22 12:39:05

+0

欢迎使用stackoverflow或者count,对于这个答案+1。 – 2012-03-22 21:13:51

+0

我不是Crypto ++的专家,但似乎该库不支持直接加载PEM编码证书。您需要添加该功能。通过直接在你的'rsa'变量上使用std :: string设施剥离开始/结束标记,或者编写执行相同工作的'CryptoPP :: BufferedTransformation'。 – orLcount 2012-03-23 09:37:16

2

我知道这是一个老问题,但其他人可能会觉得这很有用。一旦你剥去标记,你就留下了'内在'的关键材料。根据http://www.cryptopp.com/wiki/Keys_and_Formats#BER_and_DER_Encoding,您可以使用BERDecodePrivateKey加载此项。所以,加载有其标志剥夺你可以这样做

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); 
} 
1

的OpenSSL的钥匙......我想转换PEM文件在程序内自动DER文件。

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

它的一个附加到库中,而不是库适当的一部分。您下载一个ZIP并将五个源文件添加到库中。然后你建立这个库(Crypto ++会自动选取它们)。 ZIP包含五个额外的源文件,一个使用OpenSSL创建测试密钥的脚本,一个用于测试读写密钥的C++程序,以及一个用于验证由Crypto ++使用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 Pack重新实现的OpenSSL的EVP_BytesToKey,所以密钥导出会工作,你可以互操作:

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

std::string pass = "<super secret password>"; 
CryptoPP::PEM_Load(file, pk, pass.data(), pass.size()); 

CryptoPP::AutoSeededRandomPool prng; 
bool = pk.Validate(prng, 3); 
if (! valid) 
    throw ... 

还有一个PEM_Save,这样你就可以从加密直接写钥匙++。例如:

// 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_Save的加密密钥(或你打算加密):

// 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()); 

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