Rails 5.2 introduces Credentials which replaces Secrets and Encrypted Secrets from previous Rails versions. I have previously written about Credentials for those of you wanting to know more.
The key used to encrypt credentials, called the Rails master key, is automatically generated when you create a new Rails app or when you bin/rails credentials:edit
bin/rails runner 'puts ActiveSupport::EncryptedFile.generate_key'
A sample output 3c134fbe372d70b309852d98874661b2
For the Credentials feature, Rails uses the encryption aes-128-gcm
The Rails master key is in hexadecimal. Two of these make up a byte so our key is 16 bytes or 128 bits.
Put another way, each hex is 4 bits since it can have 16 values. 4 bits for each of the 32 is 128.
Looking at the Rails source ActiveSupport::EncryptedFile.generate_key
calls
SecureRandom.hex(ActiveSupport::MessageEncryptor.key_len(CIPHER))
The key length of the aes-128-gcm
OpenSSL
OpenSSL::Cipher.new('aes-128-gcm').key_len
=> 16
The SecureRandom.hex
code above is equivalent to
OpenSSL::Random.random_bytes(16).unpack('H*')[0]
unpack
H*
random_bytes
Whey did Rails choose 128 bits? Is it secure?
Key lengths can be confusing because you encounter different numbers and recommendations. For example, when creating an SSH RSA key, you need to use at least a 2048-bit key. This is way larger than 128 bits.
AES is a symmetric cipher. You can’t compare it with RSA, an asymmetric cipher. AES supports only 3 key lengths – 128, 192, and 256. Choosing a larger key isn’t always a good idea because of performance reasons. In the case of AES, 128 is secure enough. It will take several decades to break an AES 128-bit key in the absence of quantum computers.
It is interesting to note that key lengths for symmetric ciphers only matters if a brute-force attack is the best-known attack. If an analytical attack exists, a large keyspace does not help at all. In the case of AES, no such attack exists and that’s why it’s the currently most used symmetric cipher today.