RSA_PUBLIC_ENCRYPT(3)

๐Ÿ“ฆ version 4.1.0, in opensuse-leap 16.0

๐Ÿ’– RSA_PUBLIC_ENCRYPT(3) ๐Ÿ’–

okay bestie, so this is the RSA_PUBLIC_ENCRYPT(3) page from the Library Functions Manual and it's literally all about RSA public key cryptography โ€” we're talking RSA_public_encrypt, RSA_private_decrypt, EVP_PKEY_encrypt_old and EVP_PKEY_decrypt_old. grab a snack, we're doing crypto ๐ŸŽ€


โœจ NAME โœจ

RSA_public_encrypt, RSA_private_decrypt, EVP_PKEY_encrypt_old, EVP_PKEY_decrypt_old โ€” RSA public key cryptography, the whole squad ๐Ÿซถ


๐ŸŒธ SYNOPSIS ๐ŸŒธ

first, the RSA girlies โ€” pull them in with:

#include <openssl/rsa.h>

int
RSA_public_encrypt(int flen, const unsigned char *from,
    unsigned char *to, RSA *rsa, int padding);

int
RSA_private_decrypt(int flen, const unsigned char *from,
    unsigned char *to, RSA *rsa, int padding);

and then the EVP versions, different header, don't @ me:

#include <openssl/evp.h>

int
EVP_PKEY_encrypt_old(unsigned char *to, const unsigned char *from,
    int flen, EVP_PKEY *pkey);

int
EVP_PKEY_decrypt_old(unsigned char *to, const unsigned char *from,
    int flen, EVP_PKEY *pkey);

๐Ÿ’… DESCRIPTION ๐Ÿ’…

the encrypting side ๐Ÿฆ‹

RSA_public_encrypt() takes those flen bytes sitting at from (usually a session key, iykyk) and encrypts them using the public key rsa, then drops the ciphertext in to. and to? it must point to RSA_size(rsa) bytes of memory. no cap, that's the vibe check. โœจ

padding is one of these modes, and honestly each one has main character energy of its own:

  • RSA_PKCS1_PADDING โ€” PKCS #1 v1.5 padding. currently the most widely used mode, the popular girl of padding ๐Ÿ’–
  • RSA_PKCS1_OAEP_PADDING โ€” EME-OAEP as defined in PKCS #1 v2.0, with SHA-1, MGF1 and an empty encoding parameter. this one is recommended for all new applications ๐Ÿ‘‘
  • RSA_NO_PADDING โ€” raw RSA encryption ๐Ÿ’€ this mode should only be used to implement cryptographically sound padding modes inside your own application code. encrypting user data directly with RSA is insecure, fr fr, do not do it.

now the size rules, and yes they matter, memorize them:

flen must be less than RSA_size(rsa) - 11 for the PKCS #1 v1.5 based padding modes, less than RSA_size(rsa) - 41 for RSA_PKCS1_OAEP_PADDING, and exactly RSA_size(rsa) for RSA_NO_PADDING. that's it, that's the math ๐Ÿงฎ

the decrypting side ๐ŸŒˆ

RSA_private_decrypt() decrypts the flen bytes at from using the private key rsa and stores the plaintext in to. and to here needs to point to a memory section big enough to hold the decrypted data โ€” which, fun fact, is smaller than RSA_size(rsa). padding is whatever padding mode was used to encrypt the data in the first place, so keep track bestie ๐Ÿ˜ญ

the deprecated wrappers ๐Ÿ™ˆ

  • EVP_PKEY_encrypt_old() โ€” a deprecated wrapper around RSA_public_encrypt() that uses the RSA public key stored in pkey and RSA_PKCS1_PADDING.
  • EVP_PKEY_decrypt_old() โ€” a deprecated wrapper around RSA_private_decrypt() that uses the RSA private key stored in pkey and RSA_PKCS1_PADDING.

โญ RETURN VALUES โญ

  • RSA_public_encrypt() and EVP_PKEY_encrypt_old() return the size of the encrypted data โ€” i.e. RSA_size(rsa). iconic.
  • RSA_private_decrypt() and EVP_PKEY_decrypt_old() return the size of the recovered plaintext.

on error? -1 comes back ๐Ÿ˜ญ and you can grab the error codes with ERR_get_error(3).

and there's a bonus rule on top of everything above: EVP_PKEY_encrypt_old() may also return 0 if the EVP_PKEY_id(3) of pkey is not EVP_PKEY_RSA. rude but fair ๐Ÿ’€


๐Ÿฆ‹ SEE ALSO ๐Ÿฆ‹

EVP_PKEY_decrypt(3), EVP_PKEY_encrypt(3), RSA_meth_set_priv_dec(3), RSA_new(3), RSA_size(3) โ€” go read these next, they're the supporting cast ๐Ÿซถ


๐ŸŒŸ STANDARDS ๐ŸŒŸ

SSL, PKCS #1 v2.0 ๐ŸŽ€


๐Ÿงš HISTORY ๐Ÿงš

RSA_public_encrypt() and RSA_private_decrypt() showed up in SSLeay 0.4 or earlier and have been available since OpenBSD 2.4. veterans, honestly ๐Ÿ‘‘

EVP_PKEY_encrypt() and EVP_PKEY_decrypt() first appeared in SSLeay 0.9.0 and have been available since OpenBSD 2.4. then they got renamed to EVP_PKEY_encrypt_old() and EVP_PKEY_decrypt_old() in OpenSSL 1.0.0 and OpenBSD 4.9. glow-up via rebranding โœจ

RSA_NO_PADDING is available since SSLeay 0.9.0. and OAEP was added in OpenSSL 0.9.2b ๐ŸŒธ


๐Ÿ’€ BUGS ๐Ÿ’€

okay this part is serious, listen up:

decryption failures in the RSA_PKCS1_PADDING mode leak information which can potentially be used to mount a Bleichenbacher padding oracle attack. this is an inherent weakness in the PKCS #1 v1.5 padding design. prefer RSA_PKCS1_OAEP_PADDING. ๐Ÿ”ฅ

like, actually prefer it. for real. ๐Ÿซถ


and that's the page bestie! ๐Ÿ’œ this one came from Debian, dated September 10, 2023 โ€” RSA_PUBLIC_ENCRYPT(3), signing off ๐ŸŽ€โœจ

๐Ÿ“ฆ where this page comes from