Sometimes I need to encrypt some stuff but do not want to install PGP or GPG. I typically use OpenSSL for this kind of thing and have written a simple frontend script to achieve strong password based encryption using OpenSSL. Sometimes you need public / private key encryption though, below will show you how to do it using just OpenSSL.
Public/Private key encryption is a method used usually when you want to receive or send data to thirdparties. The system requires everyone to have 2 keys one that they keep secure - the private key - and one that they give to everyone - the public key. Data encrypted using the public key can only ever be unencrypted using the private key. This method of encryption that uses 2 keys is called asymmetric encryption.
So by example if Person A want to send Person B data in a secure fashion she just have to encrypt it with Person B's public key, only Person B can then open the file using her private key. There are other advantages to this kind of encryption. If I met you in person and gave you my public key, I can send you something electronically using my private key to encrypt it, if the public key you have can decrypt that data then you can trust that it was sent by me, it's mathematical proof of identity. This is the basis for Digital Signatures.
Using OpenSSL on the command line you'd first need to generate a public and private key, you should password protect this file using the -passout argument, there are many different forms that this argument can take so consult the OpenSSL documentation about that.
$ openssl genrsa -out private.pem 1024
This creates a key file called private.pem that uses 1024 bits. This file actually have both the private and public keys, so you should extract the public one from this file:
$ openssl rsa -in private.pem -out public.pem -outform PEM -pubout
You'll now have public.pem containing just your public key, you can freely share this with 3rd parties.
You can test it all by just encrypting something yourself using your public key and then decrypting using your private key, first we need a bit of data to encrypt:
$ echo 'too many secrets' > file.txt
You now have some data in file.txt, lets encrypt it using OpenSSL and the public key:
$ openssl rsautl -encrypt -inkey public.pem -pubin -in file.txt -out file.ssl
This creates an encrypted version of file.txt calling it file.ssl, if you look at this file it's just binary junk, nothing very useful to anyone. Now you can unencrypt it using the private key:
$ openssl rsautl -decrypt -inkey private.pem -in file.ssl -out decrypted.txt
You will now have an unencrypted file in decrypted.txt:
$ cat decrypted.txt
too many secrets
All of these examples use the RSA encryption method, some hard core mathematical information about it here.

I've yet to try this. You say that the encrypted file is binary junk, one of the nice things about GPG/PGP is that you can ascii armour it, so your binary junk is now ascii junk - making it more resilient when sending via email. I don't see anything like this in openssl's man page. Is there such functionality to you knowledge?
yeah rsautl can't do ASCII mode, the other encryption methods in openssl can though - the linked crypt script has that option.
All mail clients though have sorted out attaching binary data without options though, the mail clients mime encodes data, seems more appropriete for the mail clients to make the data SMTP friendly to me anyway.
Thanks! I've been looking all over for this!
Hi,
If I have some pretty big file to encrypt, the above method is not good enough. The best way to do that is to encrypt the file using secret key and then to encrypt secret key using public/private pair of keys. My question is how can I encrypt my big file with secret key using openssl?
Thanks,
Michael
Basically, it boils down to this:
--- Generate secretkey:
"dd if=/dev/random of=secretkey bs=1k count=1"
--- Symmetric encryption:
"openssl enc -blowfish -pass file:secretkey < bigfile > bigfile.bf"
--- Symmetric decryption:
"openssl enc -d -blowfish -pass file:secretkey < bigfile.bf > bigfile".
Who dislikes the idea of binary junk, look at converters/base64.
Would there be any issues with using a real cert (like one issued for email from Verisign)?
It only uses the keys, not the certificates so Verisign and co doesn't come into play.
Ok..I tried it with a real cert I exported from thunderbird that was issued to me from Verisign...
As a test I did the following...
1. Exported my certificate from thunderbird as a pkcs12 (.p12)
formatted file (its the only format it will let me export it as)
2. Converted it to a PEM formatted file
openssl pkcs12 -clcerts -in cert.p12 -out cert.pem
3. Extracted the public key
openssl rsa -in cert.pem -out public.pem -outform PEM -pubout
4. Tried to encrypt a file using the public key
openssl rsautl -encrypt -inkey cert.pem -pubin -in test.pdf -out
test.ssl
RSA operation error
1047:error:0406D06E:rsa routines:RSA_padding_add_PKCS1_type_2:data too
large for key size:rsa_pk1.c:151:
I'm missing something fundamental somehow...any help would be greatly
appreciated.
I am having the same issues. Did you have any luck with encrypting or signing using rsautl?
you've two options:
1) encrypt the file in chunks smaller than the max size
2) encrypt the file using something like password based approach as I mention in the first paragraph, then use public/private key encryption to send the password.
It's just a "feature" of the algorithm that it has a maximum block size.
Doug, maybe I'm way off, but you did:
openssl rsautl -encrypt -inkey cert.pem -pubin -in test.pdf -out
test.ssl
but according to the rsautl man page, the pubin option tells openssl that cert.pem is an RSA public key. If you're going to use your certificate, I think you should be using the certin option instead of the pubin option.
Doug, seems I jumped the gun on my last post. R.I.Pienaar is correct in his statements. If all you're trying to do is verify being able to use your cert, just try a file "smaller than the max size". For a 1024-bit key (typical for certs?), I think it can encrypt only up to 1024 bits (128 bytes).
Makes me wonder though: how does an email program encrypt an email that's larger than the "max size" associated with the certificate/key? Does it really break the email up into smaller chunks???
Hey Gregg,
Thanks for your comments, I've seen some code in PHP for encrypting larger files and they do literally run the encryption several times - once per chunk - it sux a bit, there are more suited encryption methods though for larger chunks of data.
In reply to Greg,
I think the method used in email is to encrypt the body of the email with a symmetric algorithm using a totally random 'session' key which is only a few dozen bytes long. -- RSA then encodes that session key.
That way you can CC the same encrypted message to ten different people with ten different public/private key pairs without having to send ten encrypted duplicates of the whole message.
so the RSA utility doesn't need to process long messages -- it's only intended for encrypting the keys that are used with other algorithms.
Please help me.
I Understand how to create pair Public - Private keys. But I cannot understand how to create certificate for this keys (x.509 certificate for digital sign). Could you help me and explain?