【问题标题】:Use Crypto++ RSA::PublicKey to decrypt cipher text使用 Crypto++ RSA::PublicKey 解密密文
【发布时间】:2016-06-14 06:04:02
【问题描述】:

我有用于 RSA 算法的 n、d、e。但是,我想使用 private_key 加密一些字符串,生成 USER_CERTIFICATION,然后使用 public_key 让用户解密它并获取字符串。我知道如果我这样做,任何人都可以轻松解密该字符串,但安全性完全不是我关心的问题,我只需要 除了我之外没有人可以生成USER_CERTIFICATION

我正在使用 CryptoPP,编码的代码可以正常工作:

Integer _n(...), _e(...), _d(...);
AutoSeededRandomPool rng;
RSA::PrivateKey k;
k.Initialize(_n, _e, _d);
RSAES_PKCS1v15_Encryptor enc(k);
std::string cipher;
StringSource ss1( plain, true,
    new PK_EncryptorFilter( rng, enc,
        new StringSink( cipher )) // PK_EncryptorFilter
    ); // StringSource

但解密代码抛出异常:“class CryptoPP::InvertibleRSAFunction: Missing required parameter 'Prime1'”

Integer _n(...), _e(...);

AutoSeededRandomPool rng;
RSA::PublicKey k;
k.Initialize(_n, _e);
RSAES_PKCS1v15_Decryptor dec(k);
std::string plain;
StringSource ss1( cipher, true,
    new PK_DecryptorFilter( rng, dec,
        new StringSink( plain ))
    ); // StringSource

CryptoPP 可以做到这一点吗?

【问题讨论】:

    标签: c++ rsa private-key crypto++


    【解决方案1】:

    我想用 private_key 加密一些字符串

    通常,当您要求使用私钥加密时,您需要的是带有恢复的概率签名(PSSR)方案。顺便说一句,用私钥加密不是有效的加密转换:)

    cryptlib.h header 被描述为为该库提供统一接口的抽象基类。所有 Crypto++ 签名者和验证者都遵循PK_SignatureScheme 接口。签名者进一步实现PK_Signer,而验证者进一步实现PK_Verifier

    Crypto++ RSA 对象如下所示:

    RSASS<PSSR, SHA256>::Signer signer;
    RSASS<PSSR, SHA256>::Verifier verifier;
    

    Crypto++ Rabin 对象如下所示:

    RabinSS<PSSR, SHA256>::Signer signer;
    RabinSS<PSSR, SHA256>::Verifier verifier;
    

    Crypto++ Rabin-Williams 对象如下所示:

    RWSS<PSSR, SHA256>::Signer signer;
    RWSS<PSSR, SHA256>::Verifier verifier;
    

    对象是一致的,你可以交换它们。

    顺便说一句,您应该研究一下 Rabin-Williams,看看它是否符合您的需求。另请参阅 Bernstein 的 RSA signatures and Rabin–Williams signatures: the state of the art


    我正在使用 CryptoPP,编码的代码可以正常工作...

    报废它。您使用的指数是众所周知的,因此您所做的事情没有真正的安全性。有一些方法可以提高安全性,但听起来你想要一个 PSSR。

    以下是 wiki 中使用 RSA 的 PSSR 的两个示例:

    这是RSA Probabilistic Signature Scheme with Recovery 的签名者代码,其中包含您拨入的一些内容。请注意,您需要一个真实的RandomNumberGenerator,因为签名是随机的。

    Integer n(...), e(...), d(...);
    RSA::PrivateKey key(n,e,d);
    RSASS<PSSR, SHA256>::Signer signer(key);
    
    ////////////////////////////////////////////////
    // Sign and Encode
    SecByteBlock signature(signer.MaxSignatureLength(messageLen));
    
    AutoSeededRandomPool rng;
    size_t signatureLen = signer.SignMessageWithRecovery(rng, message, messageLen, NULL, 0, signature);
    
    // Resize now we know the true size of the signature
    signature.resize(signatureLen);
    

    这里是RSA Probabilistic Signature Scheme with Recovery 的验证码,您的一些资料已拨入。请注意,您不需要RandomNumberGenerator,因此您可以在需要时使用NullRNG()

    Integer n(...), e(...);
    RSA::PublicKey key(n,e);
    RSASS<PSSR, SHA256>::Verifier verifier(key);
    
    ////////////////////////////////////////////////
    // Verify and Recover
    SecByteBlock recovered(
        verifier.MaxRecoverableLengthFromSignatureLength(signatureLen)
    );
    
    DecodingResult result = verifier.RecoverMessage(recovered, NULL, 0, signature, signatureLen);
    
    if (!result.isValidCoding) {
        throw Exception(Exception::OTHER_ERROR, "Invalid Signature");
    }
    
    ////////////////////////////////////////////////
    // Use recovered message
    //  MaxSignatureLength is likely larger than messageLength
    recovered.resize(result.messageLength);
    

    ...但是解密代码抛出异常:“class CryptoPP::InvertibleRSAFunction: Missing required parameter 'Prime1'”

    是的,用私钥加密不是有效的加密转换。我很确定用公钥解密不是有效的,要么:)


    我不打算提供加密和解密的代码,因为我认为你不需要它。但是你可以在 Crypto++ wiki 上的 RSA Encryption Schemes 找到它。

    【讨论】:

    • SignatureWithRecovery 有效,但它无法处理大于 128 字节的消息。将长消息分成许多 128 字节的块似乎不是一个好主意。现在我使用a_exp_b_mod_c(message, d, n) 自己进行编码。
    • @aj3423 - 就这样没有惊喜......你的信息仍然太大。 a_exp_b_mod_c 默默地截断它。如果您执行反向转换,那么您将收到一条截断的消息。查看Raw RSA,并检查您恢复的消息(相关部分是Private Key Encryption)。为了避免截断:是否可以增加模数的大小或使用更小的消息?
    • @aj3423 - 还要确保您真的想要放弃对签名的随机化。引用的 Bernstein 论文在第 5 节中谈到了为什么要随机化签名。针对非随机化签名的攻击自 1979 年就已存在。
    • 是的,我必须将消息拆分为 244 字节的片段以进行 pkcs1v15 填充,我认为 24​​4 仍然比 128 字节好。稍后我会尝试ApplyFunction + CalculateInverse,谢谢。
    • @aj3423 - 听起来不错。您可能还想在 Google Scholar 上搜索:"pss-r" large message,看看有哪些适合您需要的替代方案。
    【解决方案2】:

    那么,您想用您的私钥签署消息吗?这个链接有一个例子,也许它有帮助(下面的代码和链接)。另请注意,并非所有签名都是加密的。例如,比特币使用的 ECDSA 使用了一种以随机数作为输入的签名操作,在签名过程中不进行任何加密。

    https://www.cryptopp.com/wiki/User_Guide:_rsa.h

    void Sign()
    {
    string strContents = "A message to be signed";
    //FileSource("tobesigned.dat", true, new StringSink(strContents));
    
    AutoSeededRandomPool rng;
    
    //Read private key
    CryptoPP::ByteQueue bytes;
    FileSource file("privkey.txt", true, new Base64Decoder);
    file.TransferTo(bytes);
    bytes.MessageEnd();
    RSA::PrivateKey privateKey;
    privateKey.Load(bytes);
    
    //Sign message
    RSASSA_PKCS1v15_SHA_Signer privkey(privateKey);
    SecByteBlock sbbSignature(privkey.SignatureLength());
    privkey.SignMessage(
       rng,
       (byte const*) strContents.data(),
       strContents.size(),
       sbbSignature);
    
       //Save result
       FileSink sink("signed.dat");
       sink.Put((byte const*) strContents.data(), strContents.size());
       FileSink sinksig("sig.dat");
       sinksig.Put(sbbSignature, sbbSignature.size());
    }
    

    【讨论】:

    • @jwwYes,但在我看来,他想做的是经典的 compute-hash-of-msg->encrypt--hash-with-private-key。然后,如果该密钥经过 CA 验证和信任,则接收者可以使用发送者的公钥来验证 msg 的真实性。
    猜你喜欢
    • 2014-11-10
    • 2012-04-07
    • 2019-06-26
    • 1970-01-01
    • 1970-01-01
    • 2014-04-29
    • 1970-01-01
    • 1970-01-01
    • 2017-06-22
    相关资源
    最近更新 更多