# Security considerations on “expand 32-byte k”-magic number in the Salsa20 family of stream ciphers?

I'm currently examining the NaCl library written by Daniel J. Bernstein and I noticed that the library hard codes the sigma:

static const unsigned char sigma[16] = "expand 32-byte k";


In all the salsa stream implementations:

crypto_stream_xsalsa20
crypto_stream_salsa20
crypto_stream_salsa2012
crypto_stream_salsa208


and the crypto_box library wrapper:

static const unsigned char sigma[16] = "expand 32-byte k";
static const unsigned char n[16] = {0};

int crypto_box_beforenm(
unsigned char *k,
const unsigned char *pk,
const unsigned char *sk
)
{
unsigned char s[32];
crypto_scalarmult_curve25519(s,sk,pk);
return crypto_core_hsalsa20(k,n,s,sigma);
}


As far as I understand from the paper the constant is used to expand the Stream Cipher.

Now:

• Why is this variable hardcoded in the library?
• Would it make sense to change this magic string to a different value?
• Edit: What are the security considerations of using the sigma as provided in the library?

Implementations can be found in the files:

crypto_box/curve25519xsalsa20poly1305/ref/before.c
crypto_stream/salsa2012/ref/xor.c
crypto_stream/salsa2012/ref/stream.c
crypto_stream/salsa20/ref/xor.c
crypto_stream/salsa20/ref/stream.c
crypto_stream/salsa208/ref/xor.c
crypto_stream/salsa208/ref/stream.c
crypto_stream/xsalsa20/ref/xor.c
crypto_stream/xsalsa20/ref/stream.c


Edit: I found the reference to this constant in the paper referenced above as "Salsa20" constant:

(x0; x5; x10; x15) = (0x61707865; 0x3320646e; 0x79622d32; 0x6b206574); in other words, (x0; x5; x10; x15) is the Salsa20 constant.

which is "expand 32-byte k" considering endianness.

• Your third question is way too broad. The first is very simply answered: because (X)Salsa uses this constant. The second is less simple though. In general the answer would be "yes", but there probably are weak values that you shouldn't use (like all zeroes). – orlp Oct 21 '13 at 11:00
• If you are interested in (X)Salsa, and it's successor ChaCha, I'd suggest reading these papers: cr.yp.to/snuffle/salsafamily-20071225.pdf cr.yp.to/snuffle/spec.pdf cr.yp.to/snuffle/design.pdf cr.yp.to/snuffle/xsalsa-20110204.pdf cr.yp.to/chacha/chacha-20080128.pdf – orlp Oct 21 '13 at 11:02
• Choosing all four 32-bit words of the constant as equal is probably a bad idea. – CodesInChaos Oct 21 '13 at 11:02
• I now found a reference to this constant in the paper. I must confess that I find the usage of this constant a bit frightening. – Pascal Oct 21 '13 at 13:10

Salsa20 has strong rotational symmetry. The main point of these constant is that they're not invariant under rotations, introducing an asymmetry. The precise value isn't very important, as long as it's sufficiently asymmetric.

Notes on the diagonal constants

Each Salsa20 column round affects each column in the same way starting from the diagonal. Each Salsa20 row round affects each row in the same way starting from the diagonal. Consequently, shifting the entire Salsa20 hash-function input array along the diagonal has exactly the same effect on the output.

The Salsa20 expansion function eliminates this shift structure by limiting the attacker’s control over the hash-function input. In particular, the input diagonal is always 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574, which is different from all its nontrivial shifts. In other words, two distinct arrays with this diagonal are always in distinct orbits under the shift group.

Similarly, the Salsa20 hash-function operations are almost compatible with rotation of each input word by, say, 10 bits. Rotation changes the effect of carries that cross the rotation boundary, but it is consistent with all other carries, and with the Salsa20 operations other than addition.

The Salsa20 expansion function also eliminates this rotation structure. The input diagonal is different from all its nontrivial shifts and all its nontrivial rotations and all nontrivial shifts of its nontrivial rotations. In other words, two distinct arrays with this diagonal are always in distinct orbits under the shift/rotate group.

Another relevant document is the somewhat ranty Response to "On the Salsa20 core function".

SipHash shares some design principles with Salsa20 and has a similar constant. The paper justifies this as:

Choice of constants. The initial state constant corresponds to the ASCII string “somepseudorandomlygeneratedbytes”, big-endian encoded. There is nothing special about this value; the only requirement was some asymmetry so that the initial $v_0$ and $v_1$ differ from $v_2$ and $v_3$. This constant may be set to a “personalization string” but we have not evaluated whether it can safely be chosen as a “tweak”. Note that two nonzero words of initialization constants would have been as safe as four.

Would it make sense to change this magic string to a different value?

Keep it unchanged. There might be some rare scenarios where it's useful to customize the constant, but in general you should not.

In response to a question on the CurveCP mailing list, Bernstein wrote:

Is there a recommendation to customise sigma per application ?

No.

• Thank you for the thorough answer and the additional links! And no, I won't change the constant. – Pascal Oct 21 '13 at 14:51
• What rare scenarios would make it useful to customize the constant, other than to produce a "different" cipher that has no equivalent keys in common with the original Salsa20? – forest Mar 26 '18 at 0:31