1
votes

When encrypting with AES, you need to have a key size of either 128, 192 or 256 bits. But on various encrypting websites you can use any key that can even be 1 character long (8 bits).

http://aesencryption.net/

For example, on that website I can use any key I want and it will encrypt/decrypt just fine.

How does that work? How is it possible to use keys that aren't even the correct length?

3
Perhaps they pad the key with 1's or 0's. Or just repeat the key until it fills up the number of bits. A variety of methods can be used to ensure that the key is the fixed number of bits. - lurker
@lurker Thanks, 0's were in fact being padded into the key bytes until it reached a valid amount of bits. - ThePerplexedOne

3 Answers

3
votes

Many encryption tools (and libraries) allow you to provide a 'password', which it uses to derive an appropriately sized key. In order to prevent ambiguity, the term cryptographic key is often used to refer to the N-bit key used with an encryption algorithm.

If you look at the code on the page you linked, it's calculating a SHA-1 hash of the key you gave it, and taking the first 16 bytes as a 128-bit cryptographic key.

1
votes

PHP, OpenSSL (and others)

Many web sites specifically use PHP mcrypt_encrypt. PHP mcrypt used to accept keys and IV's of any size. What happened was that a key unsupported by the algorithm was extended to the first available size larger than the key bytes given. If the key was too large, it was cut down to the highest key size.

For PHP this changed in 5.6.0:

Invalid key and iv sizes are no longer accepted. mcrypt_encrypt() will now throw a warning and return FALSE if the inputs are invalid. Previously keys and IVs were padded with '\0' bytes to the next valid size.

This will probably break quite a few sites.

Note that this kind of key expansion is absolutely not best practice and is not just frowned upon by cryptography experts. Instead a key derivation function or KDF should be used.

Hashing using a hash function

Hashing using a cryptographic hash such as MD5 or SHA-1 can be used as a poor mans KDF. It doesn't provide the protection that a PBKDF offers though (see below). It is relatively safe to take the (leftmost) bytes if a key of shorter size is required. If a hash is used it should be clear from the API or source code.

This seems to be the method used in the example in the question.

Seeding a random number generator

Unless it is abundantly clear from the API what algorithm is used and that the DRBG a given seed is not mixed with previous seed data (e.g. by the operating system) then this method should not be used. In general using the key/password as seed to a random number generator will lead to catastrophic failure. This method should be fought with all possible means. A random number generator is not a KDF. Unfortunately there are many people following bad examples.

Password encryption

Instead, for password based encryption (PBE), a PBKDF (Password Based Key Derivation Function) should be used. Examples of PBKDFs are PBKDF2, bcrypt or scrypt. This is usually explicit in the API or clearly visible in source code. A good PBKDF uses a salt, possibly a pepper (secret value) and a work factor or iteration count. This makes the password - which usually does contain less entropy than a full key - to be somewhat more safe. It won't protect against really weak keys though.

Secret key derivation

If you have a secret that does contain enough entropy then the salt and work factor are not needed (a salt can however make your KDF much more secure). A work factor only adds a constant amount of time to your key derivation - if brute force attacks are already not feasible because of the amount of entropy the work factor will only slow down the intended user and CPU. Arguably the most advanced KBKDF currently is HKDF. It may be tricky to find KDFs implemented in cryptographic libraries.

1
votes

The http://aesencryption.net/ algorithm takes a key in string form and remaps it to an array which has a length accepted by Rijndael. If longer than 256 bits, the key is truncated to that length, otherwise it is padded with '\0' bytes until it reaches one of the accepted lengths for the algorithm, that is 128, 160, 192, 224 or 256 bits.

I reproduced the behaviour of this site by taking the key, converting it to an array and eventually truncating / padding it.

You can use the algorithm below to reproduce the key transformation of the site http://aesencryption.net

public static byte[] transformKey(String inputKey){ 
    int keySize = Math.min(((((sessionKey.length * 8 - 128) / 32) + 1) * 32) + 128, 256) / 8;
    sessionKey = Arrays.copyOf(sessionKey, keySize);

    for (int i = key.getBytes().length; i < sessionKey.length; i++) {
        sessionKey[i] = '\0';
    }
    return sessionKey;
}

NOTE: the for cycle is useless because Arrays.copyOf already pads the array with zeroes.