# AES key expansion question

I'm reading about the key expansion for AES but I can't seem to find the answer to this question yet. The book refers to a cipher key and the expanded key (or key schedule). This is the algorithm from the book:

procedure KeyExpansion(byte K[4][Nk], byte W[4][Nb (N r + 1)]) ? Nk ≤ 6
for j = 0 to Nk − 1 do
for i = 0 to 3 do
W[i][j] ← K[i][j]
end for
end for
for j = Nk to Nb (N r + 1) − 1 do
if j mod Nk = 0 then
W[0][j] ← W[0][j − Nk ] + S RD [W[1][j − 1]] + RC[j/Nk ]
for i = 1 to 3 do
W[i][j] ← W[i][j − Nk ] + S RD [W[i + 1 mod 4][j − 1]]
end for
else
for i = 0 to 3 do
W[i][j] ← W[i][j − Nk ] + W[i][j − 1]
end for
end if
end for
end procedure


Question 1: In the first line, this procedure is taking a key. What is the key object that needs to be accepted by this function? It looks like this key already has the requisite number of 32-bit words for 128 or 192 (since this is the key expansion for 6 columns or less) but how would you get that from a user's random length password? Would PKCS7 have already been run so that the key is padded?

Question 2: Is this showing that the user's actual entered key is part of the key schedule or are all keys in the schedule derived from the user's actual raw input key?

It looks like this key already has the requisite number of 32 bit words for 128 or 192 (since this is the key expansion for 6 columns or less) but how would you get that from a user's random length password?

How you derive the 128, 192 (or 256) bit key is outside of the AES specification. It takes as input that key; what you do to come up with the key is not its concern.

Now, we typically don't convert a user's password directly into a key; we normally either generate it from a Key Derivation Function (with inputs that may include the results of a key exchange operation), or possibly use the output of a secure random number generator directly (and contrive to somehow transmit this key to the other side). The problem with using a user's password directly is that the password is the weakest part of the system - it is far easier to try to guess a password than to break AES (or a key exchange operation).

Is this showing that the user's actual entered key is part of the key schedule or are all keys in the schedule derived from the user's actual raw input key?

The key expansion generates the 11, 13 or 15 subkeys that AES uses (depending on the key size). The initial 1, 3/2 or 2 blocks will be bits taken directly from the entered key; however that's not important to how AES works.

• Thanks for this information. Commented Feb 21, 2022 at 0:34

What is the key object that needs to be accepted by this function?

An array of bytes.

how would you get that from a user's random length password?

The usual practice is using Password-Based Key Derivation Functions (PBKDF) like PBKDF2, Bcrypt, Argon2, BalloonHash, etc. Keep in mind that they cannot increase the strength of the input. Therefore, a user must choose a good password with enough strength like a password generated with dicewire method.

In some applications like disk encryption, a uniform random key is generated for the disk encryption and this is encrypted from the key derived from the user's passwords. Still, the security depends on the quality of the password.

Also, the key material can be the source of a key exchange like DHKE, in this case a Key Derivation Function like HKDF must be applied to key material to derive AES key (bytes).

Would PKCS7 have already been run so that the key is padded?

No way, that is not secure. If you are designing a library, reject the user's (programmers') input if it is shorter than the target key size.

is this showing that the user's actual entered key is part of the key schedule or are all keys in the schedule derived from the user's actual raw input key?

The user's password should be processed with a PBKDF to derive the key. The key schedule needs a key array with size depending on the preferred AES (128,192,256). The key schedule doesn't distinguish the quality of the key material and it is not part of its design. The responsibility of the quality of the key material is on the user and libraries. The libraries that encrypt should have handled the passwords with a good PBKDF and entered the output into the key schedule. This process must be independent of the user - except for some warning about the quality of the password.

All in one;

1. Get a password from the user and warn the user if the password is short.
2. derive the desired key byte-array from the password with a PBKDF
3. Supply the key schedule with the derived key byte-array.
• "The user's password should be processed with a PBKDF to derive the key." Gotcha. Thanks. Its just that the book didn't seem to go into this as far as I can tell. Commented Feb 21, 2022 at 0:14
• What is the title of "the book"? The way an AES key is generated or derived is not part of the AES algorithm itself... Commented Feb 21, 2022 at 0:26
• @MaartenBodewes "The Design of Rijndael" in chapter 3 where the key schedule is laid out. But also FIPS 197. It's totally fine if it isn't part of AES itself but that would explain why it isn't mention and why I wasn't certain. :D Commented Feb 21, 2022 at 0:30
• @mirkaim I suspect most symmetric keys are not derived from user passwords at all. They are either generated from some asymmetric key-agreement protocol (for example TLS) or randomly generated (hopefully from a cryptographically secure random number generator), and then protected by encrypting with some other key. Commented Feb 21, 2022 at 16:14

It looks like this key already has the requisite number of 32 bit words for 128 or 192 (since this is the key expansion for 6 columns or less) but how would you get that from a user's random length password?

Passwords are not keys by themselves.

To derive a key from a password you'd use a Password Based Key Derivation Function. You could use functions such as PBKDF2, Argon2 or Balloon hashing. Other well known algorithms are bcrypt and scrypt.

Would PKCS7 have already been run so that the key is padded?

No, PKCS#7 compatible padding is what you run on the plaintext (or - when implemented efficiently - on the block-sized buffer that is used for encryption / decryption during the last encryption operation). The key doesn't need a padding method when generated / derived correctly; it should always have the right size - and otherwise zero padding would just work fine.

Is this showing that the user's actual entered key is part of the key schedule or are all keys in the schedule derived from the user's actual raw input key?

Symmetric keys consist of bits / bytes. So an AES key consist of 128, 192 or 256 bits / 16, 24 or 32 bits respectively. Anything other than that is not an AES key. A string is generally not considered a key, although it could be a hex or base64 encoding of a key. If it is a string of any size then it is generally considered a password instead.

As for the key schedule internal to AES: No, the first round(s) can very well use the original input key. As you can see the value of j does not start with j. This makes sense, the key schedule makes sure that the subkeys are sufficiently different, so that information of a later subkey doesn't present any information about an earlier subkey.

• Got it. Thanks a lot. Commented Feb 21, 2022 at 0:18