According to wikipedia both Salsa20 and ChaCha support both 128 and 256-bit keys.

The initial state for each has 8 words of key, where each word is 32 bits. 32*8 = 256. My question is... how is one supposed to expand a 128-bit key to fill in the 256-bits needed for the initial state?

The most obvious way would be to just append the 128-bit key to itself but in some ciphers, like RC2 or RC4 or Blowfish or the key goes through a key expansion step to expand the key to whatever size is ultimately needed - a key expansion step that doesn't simply append the orig key to itself.

  • 4
    $\begingroup$ Page 8 of the spec. If you're this curious about Salsa20 and ChaCha don't mess around with Wikipedia, just go straight to DJB's pages on Salsa and ChaCha and read the papers. They're short. This generalizes to other algorithms; looking up the papers usually answers your questions quicker and better than reading most third-party summaries thereof. $\endgroup$ Jan 24, 2019 at 0:57

2 Answers 2


As Luis Casillas said in his comment, the spec of Salsa is short and well explained. Namely, if you are interested in the expansion function, you can find a description with two examples (one with a 32-byte key, and one with a 16-byte key).

Short answer: when dealing with a 16-byte key, you only have to change a constant and append the key to itself.

More details bellow.

Salsa keystream generator, noted $Salsa20_k(n)$ for a key $k$ and a nonce $n$, is based on a hash function : $hSalsa20$ (called $Salsa20$ in the spec). This hash function works as follow : if $x$ is a 64-byte sequence, $hSalsa20(x)$ is a 64-byte sequence.

Now, let's see the role of the key and how it is managed. Whether you're using a 32-byte key or a 16-byte key, there is no real key expansion as you can find in Blowfish. Instead, the key $k$ is divided in two 16-bytes subkeys $k_0$ and $k_1$ (if $k$ is 16 bytes long, $k_1 = k_0$). Then, a 16-byte constant is added to the state, and that's where there is a difference : the value is not the same depending on the key size:

  • for a 16-byte key, this constant is "expand 16-byte k"
  • for a 32-byte key, this constant is "expand 32-byte k"

This constant is divided into 4 equal part, let's call them $\sigma_0,\sigma_1,\sigma_2$ and $\sigma_3$, 4-byte each.

The keystream is produced as follow : $$Salsa20_k(n) = hSalsa20(\sigma_0\ ||\ k_0\ ||\ \sigma_1\ ||\ n\ ||\ \sigma_2\ ||\ k_1 || \sigma_3)$$ where $||$ denotes the concatenation.

Notice that in both case, the argument of $hSalsa20$ is 64-byte, so 64-byte of keystream is produced. You only have to increment the nonce, and start over to generate more keystream.


My answer follows from this answer as suggested by @DannyNiu. The constant for $128$-bit ChaCha is "expand 16-byte k" in ASCII. So the four constant words are "expa", "nd 1", "6-by" and "te k" in ASCII. Converting them to HEX code we have

  1. $c_0 = 0x61707865$
  2. $c_1 = 0x312d646e$
  3. $c_2 = 0x79622d36$
  4. $c_3 = 0x6b2d6574$
  • $\begingroup$ Moderator note: this answer was merged from a different question that turned out to be a duplicate of the present question; hence the first sentence in this answer. $\endgroup$
    – fgrieu
    Sep 23, 2021 at 12:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.