Sorry that I didn't get to look at it earlier. Jim's "option 2" is cryptographically baaaaaaad. Using non-secret (possibly malleable) information as the AES key for the purpose of key-derivation raises nasty issues wrt related keys. If the application uses the same "user key" with several "transform keys" that are only slightly different, then the resulting "device keys" will be related in a bad way. I don't know if this can be exploited for cryptanalysis, but I will not be very surprised if it can.
"Option 1" is much much better, and the "lost entropy" in the keys is a non-issue (even these were 128-bit keys, and certainly for 256-bit keys). -- Shai On Jan 5, 2006, at 6:43 PM, Matt Ball wrote:
Hi Jim, Let me make sure I understand the idea. Does this describe a possible implementation of the two options?: Option 1: K2[0:127] = AES-Enc_k1(id) K2[128:255] = AES-Enc_k1(id') where id is a globally unique identifier and id' is also unique, but possibly derived from id. Option 2: K2[0:127] = AES-Enc_id(k1[0:127]) K2[128:255] = AES-Enc_id(k1[128:255]) (We have a subtle problem because the AES cipher is using a 256-bit key, but processes 128-bit blocks. To generate the derived key, it would then be necessary to perform at least two encoding operations from the AES engine.) Concerning the two options, I suspect that Option 1 might be more secure because it is not easy to compute k1 given K2. It also uses the full 256-bit k1 in the correct place in the AES block cipher (i.e. as the key input). However, with Option 1 there is an issue with creating a good value for id' (maybe use the 1's complement of id?). Also, it appears that there is likely a loss of entropy in Option 1, similar to the loss from a hashing function. In fact, I suspect the entropy loss might be greater because of using two block ciphers (each block cipher in this configuration would probably lose roughly 2/3 of a bit of entropy, for a total of 4/3 of a bit). Option 2 is more symmetric with respect to k1 and k2 and doesn't have the problem of needing an alternate id'. It would also allow a 256-bit (32 byte) id instead of 128-bit. However, if k1[0:127] == k1[128:255], then the derived K2 will also have the upper and lower halves being the same. I suspect this isn't a problem, but it does depart a little from an ideal 256-bit random permutation. Lastly, since the id is being used as a key, there might be weak key problems, although I suspect this isn't an issue. Option 2 also maintains the full entropy of k1 within K2, which is probably the most compelling reason to use this construct over a hashing function. However, the hashing function approach has a bit more flexibility with allowing variable-length inputs and also protects k1 if K2 is ever discovered. I'm personally leaning towards using HMAC, although I could be easily persuaded to use AES. Any other thoughts? -Matt