How to encrypt messages/text with RSA & OpenSSL?

In the openssl manual (openssl man page), search for RSA, and you'll see that the command for RSA encryption is rsautl. Then read the rsautl man page to see its syntax.

echo 'Hi Alice! Please bring malacpörkölt for dinner!' |
openssl rsautl -encrypt -pubin -inkey alice.pub >message.encrypted

The default padding scheme is the original PKCS#1 v1.5 (still used in many procotols); openssl also supports OAEP (now recommended) and raw encryption (only useful in special circumstances).

Note that using openssl directly is mostly an exercise. In practice, you'd use a tool such as gpg (which uses RSA, but not directly to encrypt the message).


First, if you just want good encryption, you should look at GnuPG. But if your experimenting and just want to learn how it works, you need to understand what RSA is. RSA isn't designed to encrypt any arbitrary string, it's an algorithm that encrypts an integer. Specifically, an integer from 0 to n-1 where n is the modulus value from the public key. When you talk about a RSA key that's 1024 bits, that means it takes 1024 bits to store the modulus in binary. This is one of the reasons, RSA is used in combination with a symmetric key cipher like DES or AES. You can generate a random 256 bit key for AES and encrypt that key with a 1024 bit RSA public key. Then anyone which access to the private key can extract the symmetric key and decode the message with AES. The full standard for RSA is called PKCS #1

Furthermore, DES and AES are block ciphers. They only encrypt data in block of a specific size. DES uses 64-bit blocks and AES uses 128-bit blocks. To encrypt more than a block, you must use a Mode of Operation like CBC or CTR. These modes specify how to encrypt a stream of bits using a block mode cipher.

Lastly, it's important to verify the data you are receiving. While an attacker may not be able to read data in transit, he may be able to flip bits without detection if no integrity or authenticity is applied to the data stream. An attacker can easily guess that an SSL connection to port 443 is probably a webpage request starting with GET / and he could flip bit changing it to PUT / without interfering with the rest of the encryption. A simple approach to integrity is to append an MD5 or SHA-1 sum at the end, but that only provides data integrity, not data authenticity. Any one with complete knowledge of the data stream can generate a correct sum, a more secure approach is to use a keyed-hash like HMAC which requires knowledge of a secret key to generate thereby providing data authenticity in addition to integrity.


In the below, note you can specify whatever algorithm you want, be it the ones listed or RSA (though I do not know the exact name used for RSA by OpenSSL)

use "openssl enc -help" to get a list of supported ciphers on your system, and pass that as an argument. eg, "-aes256"

Note on my system I do not have RSA in my options - at least by that name.


How do I encrypt a S/MIME message?

Let’s say that someone sends you her public certificate and asks that you encrypt some message to her. You’ve saved her certificate as her-cert.pem. You’ve saved your reply as my-message.txt.

To get the default—though fairly weak—RC2-40 encryption, you just tell openssl where the message and the certificate are located.

openssl smime her-cert.pem -encrypt -in my-message.txt

If you’re pretty sure your remote correspondent has a robust SSL toolkit, you can specify a stronger encryption algorithm like triple DES:

openssl smime her-cert.pem -encrypt -des3 -in my-message.txt

By default, the encrypted message, including the mail headers, is sent to standard output. Use the -out option or your shell to redirect it to a file. Or, much trickier, pipe the output directly to sendmail.

openssl smime her-cert.pem \
   -encrypt \
   -des3 \
   -in my-message.txt \
   -from 'Your Fullname <[email protected]>' \
   -to 'Her Fullname <[email protected]>' \
   -subject 'My encrypted reply' |\
 sendmail [email protected]

How do I sign a S/MIME message?

If you don’t need to encrypt the entire message, but you do want to sign it so that your recipient can be assured of the message’s integrity, the recipe is similar to that for encryption. The main difference is that you need to have your own key and certificate, since you can’t sign anything with the recipient’s cert.

 openssl smime \
   -sign \
   -signer /path/to/your-cert.pem \
   -in my-message.txt \
   -from 'Your Fullname <[email protected]>' \
   -to 'Her Fullname <[email protected]>' \
   -subject 'My signed reply' |\
 sendmail [email protected]

(from http://www.madboa.com/geek/openssl/ )

(er... all those backslashes - those are supposed to be escaped newlines. not sure what's going on, as it displays fine in my edit box here!