7.11 Performing Raw Decryption Using an RSA Private Key

7.11.1 Problem

You have a session key encrypted with an RSA public key (probably using a standard padding algorithm), and you need to decrypt the value with the corresponding RSA private key.

7.11.2 Solution

Your cryptographic library should have a straightforward API-to-RSA decryption algorithm: you should be able to give it the public key, the data to decrypt, a buffer for the results, and a specification as to what kind of padding was used for encryption (EME-OAEP padding is recommended; see Recipe 7.10). The size of the input message will always be equal to the bit length of RSA you're using. The API function should return the length of the result, and this length will usually be significantly smaller than the input.

If, for some reason, you need to implement RSA on your own (which we strongly recommend against), refer to the Public Key Cryptography Standard (PKCS) #1, Version 2.1 (the latest version).

7.11.3 Discussion

While RSA is believed to be secure if used properly, it is very easy to use improperly. Be sure to read the Recipe on RSA encryption and the general-purpose considerations for public key encryption in Recipe 7.1 and Recipe 7.2 in addition to this one.

When using OpenSSL, decryption can be done with the RSA_private_decrypt( ) function, defined in openssl/rsa.h and shown below. It will return the length of the decrypted string, or -1 if an error occurs.

int RSA_private_decrypt(int l, unsigned char *ct, unsigned char *pt, RSA *r, int p);

This function has the following arguments:


Length in bytes of the ciphertext to be decrypted, which must be equal to the size in bytes of the public modulus. This value can be obtained by passing the RSA object to RSA_size( ).


Buffer containing the ciphertext to be decrypted.


Buffer into which the plaintext will be written. The size of this buffer must be at least RSA_size(r) bytes.


RSA object containing the private key to be used to decrypt the ciphertext.


Type of padding that was used when encrypting. The defined constants for padding types are enumerated in Recipe 7.10.

Some implementations of RSA decryption are susceptible to timing attacks. Basically, if RSA decryption operations do not happen in a fixed amount of time, such attacks may be a possibility. A technique called blinding can thwart timing attacks. The amount of time it takes to decrypt is randomized somewhat by operating on a random number in the process. To eliminate the possibility of such attacks, you should always turn blinding on before doing a decryption operation. To thwart blinding attacks in OpenSSL, you can use the RSA_blinding_on( ) function, which has the following signature:

int RSA_blinding_on(RSA *r, BN_CTX *x);

This function has the following arguments:


RSA object for which blinding should be enabled.


BN_CTX object that will be used by the blinding operations as scratch space (see Recipe 7.4 for a discussion of BN_CTX objects). It may be specified as NULL, in which case a new one will be allocated and used internally.

7.11.4 See Also

Recipe 7.1, Recipe 7.2, Recipe 7.4, Recipe 7.10