Search code examples
c++rsaprivate-keycrypto++

Use Crypto++ RSA::PublicKey to decrypt cipher text


I have the n, d, e for RSA algorithm. However, I want to use private_key to encrypt some string, generate USER_CERTIFICATION, and use public_key for users to decrypt it and get the string. I know if I do so, the string can be easily decrypted by anyone, but security is not my concern at all, I just need that no one except me can generate the USER_CERTIFICATION

I'm using CryptoPP, the code for encoding works fine:

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

but the decryption code throws an exception: "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

Is it possible to do this with CryptoPP?


Solution

  • I want to use private_key to encrypt some string

    Usually, when you ask for encrypt with the private key, what you want is a Probablistic Signature with Recovery (PSSR) scheme. By the way, encrypt with the private key is not a valid cryptographic transformation :)

    The cryptlib.h header is described as Abstract base classes that provide a uniform interface to this library. All Crypto++ Signers and Verifiers adhere to the PK_SignatureScheme interface. Signers further implement PK_Signer, while Verifiers further implement PK_Verifier.

    The Crypto++ RSA objects would look like so:

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

    The Crypto++ Rabin objects would look like so:

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

    The Crypto++ Rabin-Williams objects would look like so:

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

    the objects are consistent, and you can swap them in and out.

    By the way, you should look into Rabin-Williams to see if it fits your needs. Also see Bernstein's RSA signatures and Rabin–Williams signatures: the state of the art.


    I'm using CryptoPP, the code for encoding works fine ...

    Scrap it. The exponent you are using is well known, so there's no real security in what you are doing. There are ways to improve the security, but it sounds like you want a PSSR instead.

    Here are the two example of using RSA's PSSR from the wiki:

    And here's the signer code for RSA Probabilistic Signature Scheme with Recovery with some of your stuff dialed in. Note that you need a real RandomNumberGenerator because the signature is randomized.

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

    And here's the verifier code for RSA Probabilistic Signature Scheme with Recovery with some of your stuff dialed in. Note that you don't need RandomNumberGenerator, so you can use NullRNG() if its needed somewhere.

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

    ... but the decryption code throws an exception: "class CryptoPP::InvertibleRSAFunction: Missing required parameter 'Prime1'"

    Yep, encrypt with the private key is not a valid cryptographic transformation. I'm pretty sure decrypt with the public key is not valid, either :)


    I'm not going to provide the code for encryption and decryption since I don't believe you need it. But you can find it at RSA Encryption Schemes on the Crypto++ wiki.