加载密钥

时间:2015-11-09 05:41:44

标签: c++ rsa digital-signature crypto++

我一直在使用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...

1 个答案:

答案 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上花了一些时间之后,你可能会厌倦那些回答他们希望 而不是 这个问题的人。我很快就厌倦了,所以我在回答时会一直保持专注(这就是我引用我回答的所有内容的原因,即使是评论)。