Fri 11 Dec 2009
Generating RSA Key Pairs in Ruby
Posted by admin under Ruby, security
[2] Comments
I’ve given a number of examples of using Public-key cryptography in blog posts and in the Strongbox documentation, but I’ve always generated the RSA key pair using the openssl command line tool, i.e.
% openssl genrsa -des3 -out private.pem 2048
Generating RSA private key, 2048 bit long modulus
......+++
.+++
e is 65537 (0x10001)
Enter pass phrase for private.pem:
Verifying - Enter pass phrase for private.pem:
% openssl rsa -in private.pem -out public.pem -outform PEM -pubout
% cat private.pem public.pem > key_pair.pem
This is fine if you want to generate a key pair once, but what if you want to do it on the fly? The Ruby OpenSSL library has support for generating key pairs:
require ‘openssl’
rsa_key = OpenSSL::PKey::RSA.new(2048)
2048 is the key size, and a good value to use for it.
What’s not obvious is how to encrypt the private key. You don’t have to encrypt it, but, if you don’t, anyone who gets a hold of the key can decrypt your data. Using an unencrypted private key gives you one layer of security (something you have – the key), encrypting it gives you an additional layer (something you know – the password).
To encrypt the private key you need a Cipher object:
cipher = OpenSSL::Cipher::Cipher.new('des3')
Then, using the Cipher object, you convert the the key_pair to PEM format:
private_key = rsa_key.to_pem(cipher,'password') public_key = rsa_key.public_key.to_pem key_pair = private_key + public_key
The resulting PEM strings be saved and then later fed to OpenSSL::PKey::RSA.new() or used with Strongbox.
All your examples use des3, but isn’t AES supposed to replace it?
Triple DES is considered secure and is currently not due to be phased out until 2030. In my experience DES3 is still much more commonly used than AES to encrypt RSA keys. However, all you need do to use AES is change:
cipher = OpenSSL::Cipher::Cipher.new(‘des3′)
to
cipher = OpenSSL::Cipher::Cipher.new(‘aes-128-cbc’)
‘aes-192-cbc’ and ‘aes-256-cbc’ work as well. You can, in fact, use and CBC cipher supported by OpenSSL, but DES3 and AES are the most common and thus portable choices across platforms.