Cipher key is always 20-bytes (with null padding) in crypt_and_hash in PolarSSL

1.2k Views Asked by At

I'm writing an application whose security is based on the crypt_and_hash example provided with the PolarSSL package. In the example, crypt_and_hash takes in a key (supplied via a command-line argument) and a random 16-byte IV. It then garbles them together 8192 times (for reasons that I don't know, but that's besides the question):

    memset( digest, 0,  32 );
    memcpy( digest, IV, 16 );

    for( i = 0; i < 8192; i++ )
    {
        md_starts( &md_ctx );
        md_update( &md_ctx, digest, 32 );
        md_update( &md_ctx, key, keylen );
        md_finish( &md_ctx, digest );

    }

Then, it takes the output and uses is to set the key in the cipher context via cipher_setkey, which is later used to perform all the encryption/decryption operations:

    if( cipher_setkey( &cipher_ctx, digest, cipher_info->key_length,
                       POLARSSL_ENCRYPT ) != 0 )

I noticed that when crypt_and_hash creates its digest, it sets only 20 bytes in its buffer, followed by 12 null bytes, regardless of the encryption scheme and the size of the key supplied. I tried different schemes and key sizes to test that. Shouldn't the key size be according to the encryption (e.g. 32 bytes for AES-256 and 16 bytes for AES-128)? Why is it always 20?

2

There are 2 best solutions below

3
On BEST ANSWER

What you have here is a proprietary Password Based Key Derivation Function (PBKDF). This function seems to allow for key strengthening or key stretching, but not for key expansion.

Key strengthening can be used to make it harder to brute force a key value (or password value) if this key is not fully random. It is implemented by the loop using the IV (which is actually a salt) and key within a cryptographic hash function. If you receive 20 bytes, this is likely to be SHA-1 as it has 160 bits of output.

Key expansion is not provided by the algorithm. Key expansion is what you are looking at: distribute the calculated random number over an X number of bits. It is relatively easily implemented; probably the best thing to do is to have a look at the key expansion algorithm of HKDF.

Currently the scheme is however limited by the output of the hash within the PBKDF. Of course, if you were to use SHA-256 you would have enough entropy for one AES-256 key. Or, if you use a different salt for each encryption, you could use SH-384 to derive an AES-256 key and use the remaining bits as IV (for the encryption).

Note that the term key stretching is not always used to mean the same thing.

0
On

crypt_and_hash is an example supplied with PolarSSL to show how to use both the cipher and md layer. If you use SHA-1 it can only get a maximum of 20 bytes (160 bits) from the MD and thus into the key to use..

If you want to use a cipher that needs a bigger key (such as AES-256) you need to use a different hash algorithm on the command-line, such as SHA-256 or SHA-512 which will fill the entire 32 bytes of the key space for you..