使用不同算法的 PKCS1v15 填充进行 Crypto++ 签名

Crypto++ Signing with PKCS1v15 padding with different algorithms

我想知道 Crypto++ 是否仅使用 SHA (RSASSA_PKCS1v15_SHA_Signer) 对文件进行签名?

我一直在使用 pyCryptodome 进行签名和验证,但我想制作一个执行相同操作的 C++ 应用程序。在 Python 中,我可以使用任何支持的散列(SHA3/BLAKE2B 等)算法对文件进行签名。至少我想支持在 C++ 中使用 SHA256 进行签名。

std::string Hasher::sign(const std::string& message)
{
    RSASSA_PKCS1v15_SHA_Signer signer(m_privateKey);
    size_t length = signer.MaxSignatureLength();
    SecByteBlock signature(length);

    length = signer.SignMessage(rng, (CryptoPP::byte*)message.c_str(), message.size(), signature);
    signature.resize(length);
    //Want the signature as a hex
    return toHex(signature, signature.size());
}

但是,我希望能够做一些与 Python 类似的事情:

def(message, key, passphrase, hashType):
   rsakey = RSA.importKey(key,passphrase)
   signer = PKCS1_v1_5.new(rsakey)
   # Get the hash class based os user given hashType ex ("SHA256" returns "SHA256.New()")
   digest = getHash(hashType)
   digest.update(message.encode("ascii"))
   return signer.sign(digest).hex()

如果我选择相同的私钥,并使用 hashType“SHA”,我将获得与我的 C++ 代码相同的签名结果。

所以我找到了答案。所以部分按照教程找到 hereRSASS<PSS, SHA256>::Signer signer(privateKey); 你可以添加 PKCS1v15 填充 RSASS<PKCS1v15, SHA256>::Signer signer(privateKey); 所以最终代码看起来像这样:

std::string Hasher::sign(const std::string& message)
{
    CryptoPP::RSASS<CryptoPP::PKCS1v15, CryptoPP::SHA256>::Signer signer(m_privateKey);
    size_t length = signer.MaxSignatureLength();
    SecByteBlock signature(length);

    length = signer.SignMessage(rng, (CryptoPP::byte*)message.c_str(), message.size(), signature);
    signature.resize(length);
    //Want the signature as a hex
    return toHex(signature, signature.size());
}

太像了,我还是不知道为什么RSASSA_PKCS1v15_SHA_Signerclass还存在。加入一些额外的东西是我的最终目标,因为我在邮件列表上除了一个随机的 13 岁 question 之外找不到任何东西: 如何使用 Crypto++ 签署和验证文件(就像您在 pyCrypto 中签署文件一样)

签名文件:

std::string Hasher::sign()
{
    CryptoPP::RSASS<CryptoPP::PKCS1v15, CryptoPP::SHA256>::Signer signer(m_privateKey);

    size_t length = signer.MaxSignatureLength();
    SecByteBlock signature(length);
    // Get bytes of the file
    const auto& data = getFileBytes();
    //AFAIK you need to create a signer PK_MessageAccumulator object to acheive this
    CryptoPP::PK_MessageAccumulator* pSigMsgAcc = signer.NewSignatureAccumulator(rng);
    //Update it with your data, toBinary_const is just a short for (const CryptoPP::byte*)data.data()
    pSigMsgAcc->Update(toBinary_const(data), data.size());

    length = signer.Sign(rng, pSigMsgAcc, signature);
    signature.resize(length);
    //I return it as hex as people can actually read the signature and verify it themself
    return toHex(signature, signature.size());
}

正在验证文件

bool Hasher::verify(const std::string& signature, const std::string& type)
{
    CryptoPP::RSASS<CryptoPP::PKCS1v15, CryptoPP::SHA256>::Verifier verifier(m_publicKey);

    const auto& data                             = getFileBytes();
    //Create a verifyer PK_MessageAccumulator object
    CryptoPP::PK_MessageAccumulator* pVrfyMsgAcc = verifier.NewVerificationAccumulator();
    pVrfyMsgAcc->Update(toBinary_const(data), data.size());
    //Here comes the down side of using hex as signatrue, I convert it to a binary string
    auto toVerify = toBinaryString(signature);
    //Then I have to convert the binary string to binary
    // (It does not like me to convert the hex directly to binary)
    verifier.InputSignature(*pVrfyMsgAcc, toBinary_const(toVerify), toVerify.size());
    return verifier.Verify(pVrfyMsgAcc);
}