I am currently implementing Salsa20 from the specification as an exercise in learning and self-flagellation.

I have Sections 1-7 passing the test examples provided. I am now stuck on Section 8, The Salsa20 hash function (Page 6):

The Salsa20 hash function

1) What is confusing is the doubleround$^1$$^0$. What does this mean exactly? Perform the doubleround function $10$ times on the $x$ words from earlier? I.e. I perform doubleround($x$) once, then feed the result of that back into the doubleround function again, then repeat that 8 more times?

2) After that it does a littleendian$^-$$^1$($z0 + x0$). I know what the littleendian function is as it was defined previously in Section 7. But what is littleendian$^-$$^1$? The inverse of it? Do I simply pass the result of the $z0$ and $x0$ addition back into the normal littleendian function again (which as a byproduct would reverse the results of the littleendian function)?

3) To produce the final output, do I concatenate the 16 words (4 bytes per word) from the littleendian$^-$$^1$ function together, then convert them to bytes to get the resulting 64-byte sequence?

Perhaps some psuedo code would answer these questions more succinctly.

Gracias amigos.


1 Answer 1


You are right about the interpretation of the power 10: it's a tenfold iteration. So we apply the function 10 times, starting with $x$, feeding the output as input for the next step. So C-like (I write x for the vector of 16 words $x_0,\ldots,x_{15}$):

y=x; for (i=0; i< 10; i++){ y = doubleround(y) }; return y

The inverse of little-endian is indeed the function that sends a word (32 bits) back to the sequence of 4 bytes in a little endian way, so the least significant byte goes first, and the most significant byte goes last. So it maps $w$ to w & 0xff, (w >> 8) & 0xff, (w >> 16) & 0xff, (w >> 24) & 0xff

Finally, the iteration gives you a vector 16 words, which you add componentwise in the same order with the original input vector. Then you convert them to bytes again, in that same order, and every word in the little-endian fashion described above. (We could also have converted them to bytes first (using the inverse of litleenian) and then done 64 byte additions in order, but this is less efficient, as we then do 64 byte additions instead of 16 word additions).

  • $\begingroup$ Muitas gracias Henno. Strangely I had interpreted the document as you had and the code already doing that in the first attempt. So I had to go through it line by line to figure out why it wasn't working. It turns out there was a bug earlier in the code so it wasn't producing the correct outputs to match the example tests. My loop was adding the littleendian words into the $x$ word array incorrectly e.g. [0, 1, 2, 3, 2, 3, 4, 5...] instead of [1, 2, 3, 4, 5, 6, 7, 8...] which is an embarrassing mistake. Anyway thanks for clarifying. Have a blessed week. $\endgroup$
    – Motox
    Commented Jan 12, 2015 at 9:18
  • $\begingroup$ Is the intention of the (w >> 8) to be the arithmetic right shift operator, or the logical right shift operator? For example, in Java and JavaScript, the arithmetic right shift operator is >>; whereas the logical right shift operator is >>>. stackoverflow.com/a/7522498. Also I think the (w >> 24) 0xff should be (w >> 24) & 0xff yes? $\endgroup$
    – Motox
    Commented Feb 19, 2015 at 11:28
  • $\begingroup$ Logical shift, and yes, & is missing $\endgroup$ Commented Feb 19, 2015 at 16:45
  • $\begingroup$ Great, thanks for clarifying! I've got it all working now. $\endgroup$
    – Motox
    Commented Feb 21, 2015 at 0:17

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.