I strongly suggest you do not try to roll your own system. Even if you are using standard and secure primitives, the design of a cryptosystem can be quite involved. You need to choose a threat model and adhere to it. The below is posted purely for informational purposes. I do not recommend you use this technique in production. While it may work in theory, it's not a good design.
Instead, you could use something like BLAKE2 or HKDF, as mentioned in a comment, which will accomplish the same thing more simply. It will furthermore allow you to derive an input of arbitrary size (you won't be limited to the AES block size, which is required for safety in ECB mode).
AES has a 128-bit block size, so although you could use AES with a 256-bit key for each of the three KDF operations, the key passing through the three AES operations itself must be only 128 bits. If you try to encrypt a 256-bit key, then the result will leak whether or not the first half of the key is identical to the second half (this is because ECB is not IND-CPA secure).
Assuming key1 is only 128 bits and at least 128 bits from key1 and the outputs of KDFC1, KDFC2, and KDFC3 are unknown to the attacker, then the resulting key will have 128 bits of security.
Below is a simple example script which shows how this can be done. A few notes about it:
The openssl command uses -nopad
, otherwise ECB mode will require padding.
The key is fed directly to openssl using -K
, which is preferred for raw keys.
The -d
flag is removed, as there is no reason to run AES in the decryption direction here.
key1=96eb4681f1704693925718d8241a425b
kdf1=d17ecb9294631d1a235b392707a390a9ea4184dc30896b9bdeaa9cbc272764e4
kdf2=90da13583ae2e5cb6ef4d6484f5e1236d26a16043c927e31fa8ef02f0d455ad6
kdf3=6de5397c280d8ce09914c8639e20a3b302f75ea811c9e76bd8638333cfabc989
encrypt() {
echo $(xxd -r -ps <<< $2 | openssl aes-256-ecb -nopad -K $1 | xxd -c32 -ps)
}
key2=$(encrypt $kdf1 $key1)
key3=$(encrypt $kdf2 $key2)
key4=$(encrypt $kdf3 $key3)
echo "result = $key4"