我一直在使用Crypto ++研究数字签名者和验证者。我遇到了以下问题:我的签名者和验证者在我使用第一个示例(生成RSA密钥对并保存它)的编程方式生成的公钥和私钥上工作得很好wiki。但是,当我使用另一个测试密钥对时,我提供了测试,我有以下错误:“BER解码错误”当尝试加载密钥进行签名时。我一直在网上搜索,但无法解决问题。这是我的课程:
class DSUtility
{
protected:
DSUtility() = default;
template<typename KeyType, typename KeySourceType>
KeyType PrepareKey_(const std::string& key_source);
};
template<typename KeyType, typename KeySourceType>
KeyType DSUtility::PrepareKey_(const std::string& key_source)
{
CryptoPP::ByteQueue key_bytes;
KeySourceType(key_source.c_str(), true, new CryptoPP::Base64Decoder).TransferTo(key_bytes);
key_bytes.MessageEnd();
KeyType key;
key.Load(key_bytes); // FAILS WHEN TRYING TO SIGN WITH ANOTHER PRIVATE KEY
return key;
}
class Signer : private DSUtility
{
public:
Signer(const std::string& private_key);
std::string Sign(const std::string& data);
private:
typedef CryptoPP::RSA::PrivateKey PrivateKey;
CryptoPP::RSASS<CryptoPP::PKCS1v15, CryptoPP::SHA256>::Signer signer_;
};
Signer::Signer(const std::string& private_key) :
signer_(PrepareKey_<PrivateKey, CryptoPP::StringSource>(private_key))
{
}
std::string Signer::Sign(const std::string& data)
{
CryptoPP::SecByteBlock signature(signer_.SignatureLength());
signer_.SignMessage(CryptoPP::AutoSeededRandomPool(), (byte const*)data.c_str(), data.size(), signature);
return std::string(signature.begin(), signature.end());
}
我的一个键(有效)看起来像这样:
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAILkZnFV77ckeZkepDk1fvsE
qli05im29PTZq0ayWZsSgis+tpzP2KpSigWimAfkOCF36Y1Zb9E8VcxBaRbEEH0ObQTQdOl0
z1Cf0mViD2dQgH+8ZucU2gKy0YDpjIJ6wZM55azNZBg1s5J9PuDyM+nMRh5RiJqEpaXSXzgV...
另一个看起来如下:
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDGwB5n/xMsDoqo+bGaws15FYGGjsJxCM2deHJZqV2QKfvkmStf
8HntPqaJ+mc9UA6ghN1uGndChg1PuHSNVaRU2x8fem/mFUhfOJaZcYich8JAy0nm
sJUOwoRqLfKjLWmqy0QZHXDDVw+sD5uq/oOvfFFjuYIcsskHQmGTfkdJrQIDAQAB...
答案 0 :(得分:1)
但是当我使用另一个测试密钥对时,我提供了测试,我在尝试加载密钥进行签名时出现以下错误:“BER解码错误”。
很难说出现了什么问题......您应该提供 真正的 测试密钥。不值得花时间尝试用“......”来解码假的,因为我们知道它会失败。
我只是猜测,但它可能是一个原始密钥(即,只有公钥或私钥,没有标识符)而不是密钥信息(即外部序列和带有内部公钥或私钥的标识符) )。后者(关键信息)有时在其公钥时被称为 subjectPublicKeyIdnfo
。
您可能需要查看Crypto ++ wiki上的Keys and Formats。你引用的指南有点旧,它是出于历史目的。这是3秒的巡演:
raw key
时,请致电BERDecode
key info
时,请致电Load
raw key
时,请致电DEREecode
key info
时,请致电Save
template<typename KeyType, typename KeySourceType> KeyType DSUtility::PrepareKey_(const std::string& key_source) { CryptoPP::ByteQueue key_bytes; KeySourceType(key_source.c_str(), true, new CryptoPP::Base64Decoder).TransferTo(key_bytes); key_bytes.MessageEnd(); KeyType key; key.Load(key_bytes); // FAILS WHEN TRYING TO SIGN WITH ANOTHER PRIVATE KEY return key; }
这可能会简化一下:
template<typename KeyType, typename KeySourceType> KeyType
DSUtility::PrepareKey_(const std::string& key_source)
{
ArraySource as((const byte*)key_source.data(), key_source.size(),
true, new Base64Decoder());
key.Load(as);
return key;
}
如果是 raw key
,您可以尝试:
key.BERDecode(as);
“......另一个看起来如下:
-----BEGIN RSA PRIVATE KEY-----
...”
对于PEM编码密钥,请参阅Crypto ++ wiki上的PEM Pack。
这是对Stack Overflow问题的引用,但它引用了Crypto ++ wiki页面(除了其他答案):Load PEM encoded private RSA key in Crypto++。
在尝试使用另一个私钥时失败
此外,“尝试签署另一个私钥时失败”与“尝试加载时失败”不同。我试图专注于你问的问题,所以它可能不是你所希望的答案。
在Stack Overflow上花了一些时间之后,你可能会厌倦那些回答他们希望 而不是 这个问题的人。我很快就厌倦了,所以我在回答时会一直保持专注(这就是我引用我回答的所有内容的原因,即使是评论)。