# OpenSSL AES 256-bit Key Management

I am using C and OpenSSL to encrypt files. After experimenting with the OpenSSL command line utility, it makes you enter a passphrase that can be any length, but uses that to create a 256-bit key.

How many passwords or keys does aes use & how does it use them? If you can make your passphrase as long or as short as you want, what is the point of having a 256-bit encryption?

-

AES is a block cipher, a cryptographic primitive. It has no involvement with key derivation or anything of that nature. The three standard key sizes are 128 bit, 192 bit, and 256 bit. How you get those keys is beyond the purview of AES, which is concerned only with encryption. As I said, it is a cryptographic primitive, meaning it is meant to be used in a larger system (usually). In fact, "AES" itself can't encrypt more than one block of data; to do that, you need to use a block cipher mode of operation. I'd recommend, for non-authenticated schemes, either CTR or CBC, not ECB. But in general, you probably want one of the authenticated modes (AEAD), like GCM, OCB, EAX, or CCM.

So, the fact that OpenSSL lets you use a passphrase is entirely unrelated to AES. Typically, I would recommend against using passphrases for encryption, as they are notoriously low-entropy and vulnerable to simple guessing. OpenSSL does use a salt by default, which improves things, but the algorithm it uses is "somewhat" questionable. The default hash function used in it is MD5, and it only uses just a few rounds by default. So, if possible, I would very highly recommend you generate a real key instead of using a passphrase. And, like your question implies, if the adversary knows your file is encrypted with a passphrase, it makes using a larger key sort of moot.

Just remember that AES was designed as a block cipher, so the whole passphrase business is really separate from it. Anyway, if you are interested in the practical differences in AES-128, AES-192, and AES-256, there are several good questions on this site with good answers:

-
The KDF isn't just “somewhat questionable”, and the real problem isn't the use of MD5: EVP_BytesToKey is called with an iteration count of 1, so there's no hardness factor, the derivation is as fast as can be. –  Gilles Jun 14 '13 at 16:53
@Gilles: I said "somewhat" questionable, not "somewhat questionable". :) –  Reid Jun 14 '13 at 17:40

Important note: If you need something that provides some real security, it would be unwise to design it and implement it from basic building blocks like this. Instead, use software that has been built to a specification, thoroughly analyzed by experts, and thoroughly tested.

If, on the other hand, you are interested in learning about cryptography, then read on.

The cryptographic primitive AES-256 cipher block accepts an 256-bit key, and 128 bits of data as input, and produces 128 bits of data as output. It is up to the designer or a cryptographic module to decide which bits to present as key and data input, what to do with the output, and in what sequence. Among other things, OpenSSL implements various block cipher modes of operation, like cipher block chaining (CBC), which partially determine these design parameters. It is outside the scope of this question, but I strongly recommend that you learn about block cipher modes.

To generate a 256-bit key, a cryptographic module could use a source of entropy to generate random bits, or it could accept a pass phrase and use an extra computational step to derive the 256-bit key from a pass phrase or other input. A key-derivation function is often based upon another kind of cryptographic primitive called a message digest or hash. For example, you could concatenate the pass phrase with a random salt, then compute the SHA-1 hash of the result, and use the first 256-bits of the SHA-1 hash as the encryption key.

The design of the key-derivation function can have a surprisingly large effect on the security of a crypto system. Read about Password-Based Key Derivation Function 2 (PBKDF2), also known as Public Key Cryptography Standard #5 (PKCS#5), which is widely used. Another example of a strong key derivation function currently under development is scrypt.

-

AES is a family of three pairs of functions that use essentially the same mechanisms with different tuning parameters: AES-128 encryption and decryption, AES-192 encryption and decryption, and AES-256 encryption and decryption. Each of these functions takes an $n$-bit key (where $n$ is 128, 192 or 256 depending on whether the function is AES-128, AES-192 or AES-256) as well as a 128-bit block as parameters, and returns a 128-bit block.

(If your data doesn't consist of exactly 128 bits, you need to apply a mode of operation around AES. When you use openssl enc, you need to select a mode of operation in addition to the key size, e.g. aes-256-cbc specifies the mode CBC with PKCS#5 padding. CBC specifies how to encrypt multiple 128-bit blocks, and PKCS#5 specifies how to pad the message to a whole number of blocks.)

AES-256 requires a 256-bit key, period. However there are different ways of building that 256-bit key. One way is to generate 256 random bits and take them as the key. You need to store these 256 bits somewhere, or you won't be able to decrypt what you've encrypted. Another way is to derive the key from some other material in a way that can be reproduced later; this is done, for example, when you only have a few hundred bits of storage and need to construct many different keys from that.

If you need the key to be memorable to a human user, presenting it as 64 hexadecimal digits or some other encoding of 256 random bits isn't practical. Instead, one method to obtain a key is to let the user enter a password (or passphrase, the two words are synonyms as far as cryptography is concerned), and derive the key from the password. The encryption algorithm doesn't operate on the password, it needs a key of exactly 256 bits.

A way to turn a password into a key is called a password-based key derivation function. Such a derivation is inherently problematic because a password doesn't have the same security properties as a random key: it has a lot less entropy (so there's a risk that it will be guessed, unlike a random key), and it can be reused (so an adversary who obtains the key from one application might be lucky with another application, unlike a random key which is practically guaranteed to be unique). Hence a password-based key derivation includes a unique salt and performs stretching to reduce the opportunity for brute-force attacks. For a thorough discussion of password hashing, which is very similar to password-based key derivation, see this answer on Security Stack Exchange.

When you specify a password instead of a key, OpenSSL applies a homemade key derivation function to the password which includes appropriate salting but only the barest amount of stretching. This means that it is very fast to attempt decryption with a guessed password.

-