aj3423
aj3423

Reputation: 2611

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?

Upvotes: 3

Views: 4741

Answers (2)

Erik Alapää
Erik Alapää

Reputation: 2713

So, you want to sign a message with your private key? This link has an example, maybe it helps (code and link below). Note also that not all signing is encryption. For example, ECDSA used by Bitcoin uses a signing operation that takes a random number as one input, no encryption is done as part of signing.

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

Upvotes: 1

jww
jww

Reputation: 102386

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.

Upvotes: 2

Related Questions