RSA Encryption Schemes
Documentation |
#include <cryptopp/rsa.h>
|
This articles shows you how to perform encryption using RSA.
For the main RSA page, visit RSA Cryptography. For signature schemes, visit RSA Signature Schemes. Raw RSA provides information about low level RSA operations. For a detailed treatment of key generation, loading, saving, validation, and formats, see Keys and Formats.
Plaintext Length
The maximum length of a plaintext string that can be encrypted with RSA can be determined by FixedMaxPlaintextLength
. On error, FixedMaxPlaintextLength
returns 0. The value returned by FixedMaxPlaintextLength
is directly related to the modulus size n and the padding scheme.
Ciphertext Length
The length of the resulting ciphertext can be determined by FixedCiphertextLength
. On error, FixedCiphertextLength
returns 0. The value returned by FixedCiphertextLength
is directly related to the modulus size n.
Buffer Sizes
When encrypting and decrypting using Crypto++, the plaintext and ciphertext buffers can be the same. This effectively means in-place encryption and decryption can be performed. However, always make sure the buffer is large enough to hold the encrypted data (which will be larger than the plaintext). If the buffers are not the same, the buffers must not overlap. Finally, both CiphertextLength
and MaxPlaintextLength
return 0 on error.
// Encrypt size_t cipherTextSize = publicKey.CiphertextLength( plainTextSize ); assert( 0 != cipherTextSize ); assert( plainTextSize >= cipherTextSize ); publicKey.Encrypt(prng, (byte*)plainText, plainTextSize, (byte*)cipherText); ... // Decrypt size_t plainTextSize = privateKey.MaxPlaintextLength( cipherTextSize ); assert( 0 != plainTextSize ); assert( cipherTextSize >= plainTextSize ); DecodingResult result = privateKey.Decrypt(rnd, (byte*)cipherText, cipherTextSize, (byte*)plainText); assert( plainTextSize == result.messageLength );
OAEP and SHA-256
The typedefs RSAES_OAEP_SHA_Encryptor
and RSAES_OAEP_SHA_Decryptor
use SHA-1 by default:
$ grep RSAES_OAEP_SHA_Encryptor *.h rsa.h:DOCUMENTED_TYPEDEF(RSAES<OAEP<SHA1> >::Encryptor, RSAES_OAEP_SHA_Encryptor); $ grep RSAES_OAEP_SHA_Decryptor *.h rsa.h:DOCUMENTED_TYPEDEF(RSAES<OAEP<SHA1> >::Decryptor, RSAES_OAEP_SHA_Decryptor);
If needed you can change the hash using OAEP
template parameter:
RSAES<OAEP<SHA256> >::Encryptor
and
RSAES<OAEP<SHA256> >::Decryptor
Crypto++ 8.7 added typedefs for RSAES_OAEP_SHA256_Encryptor
and RSAES_OAEP_SHA256_Decryptor
. Also see Commit 3b8c9303b462.
Also see How to encrypt/decrypt data using RSA OAEP SHA-256 in Crypto++ on Stack Overflow.
Sample Programs
RSA Encryption Scheme (OAEP and SHA)
The following code demonstrates RSA encryption using OAEP. SHA is used to generate the padding bits and mask the input (see OAEP_Base::Pad
).
//////////////////////////////////////////////// // Generate keys AutoSeededRandomPool rng; InvertibleRSAFunction parameters; parameters.GenerateRandomWithKeySize( rng, 1536 ); RSA::PrivateKey privateKey( parameters ); RSA::PublicKey publicKey( parameters ); //////////////////////////////////////////////// // Secret to protect static const int SECRET_SIZE = 16; SecByteBlock plaintext( SECRET_SIZE ); memset( plaintext, 'A', SECRET_SIZE ); //////////////////////////////////////////////// // Encrypt RSAES_OAEP_SHA_Encryptor encryptor( publicKey ); // Now that there is a concrete object, we can validate assert( 0 != encryptor.FixedMaxPlaintextLength() ); assert( plaintext.size() <= encryptor.FixedMaxPlaintextLength() ); // Create cipher text space size_t ecl = encryptor.CiphertextLength( plaintext.size() ); assert( 0 != ecl ); SecByteBlock ciphertext( ecl ); encryptor.Encrypt( rng, plaintext, plaintext.size(), ciphertext ); //////////////////////////////////////////////// // Decrypt RSAES_OAEP_SHA_Decryptor decryptor( privateKey ); // Now that there is a concrete object, we can check sizes assert( 0 != decryptor.FixedCiphertextLength() ); assert( ciphertext.size() <= decryptor.FixedCiphertextLength() ); // Create recovered text space size_t dpl = decryptor.MaxPlaintextLength( ciphertext.size() ); assert( 0 != dpl ); SecByteBlock recovered( dpl ); DecodingResult result = decryptor.Decrypt( rng, ciphertext, ciphertext.size(), recovered ); // More sanity checks assert( result.isValidCoding ); assert( result.messageLength <= decryptor.MaxPlaintextLength( ciphertext.size() ) ); // At this point, we can set the size of the recovered // data. Until decryption occurs (successfully), we // only know its maximum size recovered.resize( result.messageLength ); // SecByteBlock is overloaded for proper results below assert( plaintext == recovered ); cout << "Recovered plain text" << endl;
RSA Encryption Scheme (OAEP and SHA) using Filters
Using Crypto++ pipelining, the previous program can be reduced to the following.
//////////////////////////////////////////////// // Generate keys AutoSeededRandomPool rng; InvertibleRSAFunction params; params.GenerateRandomWithKeySize( rng, 1536 ); RSA::PrivateKey privateKey( params ); RSA::PublicKey publicKey( params ); string plain="RSA Encryption", cipher, recovered; //////////////////////////////////////////////// // Encryption RSAES_OAEP_SHA_Encryptor e( publicKey ); StringSource ss1( plain, true, new PK_EncryptorFilter( rng, e, new StringSink( cipher ) ) // PK_EncryptorFilter ); // StringSource //////////////////////////////////////////////// // Decryption RSAES_OAEP_SHA_Decryptor d( privateKey ); StringSource ss2( cipher, true, new PK_DecryptorFilter( rng, d, new StringSink( recovered ) ) // PK_DecryptorFilter ); // StringSource assert( plain == recovered );
Downloads
RSA-ES-OAEP-SHA-Test.zip - Demonstrates RSA-ES (OAEP/SHA)
RSA-ES-OAEP-SHA-Filter-Test.zip - Demonstrates RSA-ES (OAEP/SHA) using Filters