RSA explained
RSA is a public-key cryptosystem. A public key encrypts a message, and its corresponding private key decrypts it. Multiplying two primes is easy, but recovering the primes from a large product is difficult. This property underlies its security.
Reading the equations
gcd(a, b) is the greatest common divisor of a and b: the largest positive integer that divides both without a remainder. For example, the greatest common divisor of 12 and 18 is 6. Two numbers whose greatest common divisor is 1 are called coprime. The numbers themselves do not have to be prime.
a mod n is the remainder when a is divided by n. For example, dividing 17 by 5 gives a quotient of 3 and a remainder of 2. RSA uses the remainder modulo n rather than the full value of a large power.
a ≡ b (mod n) means that a and b leave the same remainder when divided by n. For example, 17 and 2 both leave a remainder of 2 when divided by 5.
1. Generate keys for text
Generate a 2048-bit RSA key for OAEP (SHA-256, MGF1-SHA-256, and an empty label). The small hand-calculation keys have insufficient space for OAEP. Keys and plaintext stay in your browser.
Generate keys to automatically encrypt and decrypt the text you enter.
2. Encrypt with the public key
UTF-8: 11 / 190 bytes
Encode the text as UTF-8 bytes M, then use OAEP to produce a 256-byte encoded message EM. OAEP uses a hash and a 32-byte random seed rather than simply adding zeros. Convert EM to integer m and encrypt it with RSA. The same text produces different ciphertext each time.
PS is the zero-filled string inside OAEP. Combine it with the empty-label hash (32 bytes), a delimiter (1 byte), and M, then apply an MGF1 mask derived from the random seed. EM consists of a leading byte, the masked seed (32 bytes), and masked data (223 bytes).
3. Decrypt with the private key
Recover integer m from ciphertext c using private exponent d and n. Convert it back to a 256-byte EM, validate and remove OAEP, then decode UTF-8 to recover the text. Public exponent e is not needed for decryption.
4. PEM format and OpenSSL commands
The OpenSSL 3 example below generates a separate 2048-bit key and uses OAEP (SHA-256). Plaintext is limited to 190 bytes with this key size; combine RSA with symmetric encryption for longer data.
Generate a key and extract its public key
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private.pem
openssl pkey -in private.pem -pubout -out public.pem
Save the plaintext in message.txt, then run the following commands in order. private.pem is an unencrypted private key and must be kept secure.
Encrypt a file with the public key
openssl pkeyutl -encrypt -pubin -inkey public.pem -in message.txt -out encrypted.bin -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256
Decrypt a file with the private key
openssl pkeyutl -decrypt -inkey private.pem -in encrypted.bin -out decrypted.txt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256
The original plaintext is written to decrypted.txt. OAEP uses randomness, so encrypting the same plaintext produces different ciphertext each time.
Official OpenSSL documentation