Providing working example for the essence of sc_reduce32 at Why is sc_reduce32 needed? created another question.

% echo deefd263cbfed62a3711dd133df3ccbd1c4dc4aac21d7405fd667498bf8ebaa1 | sc_reduce32 9ca838c2c31f1fbad7f030b68a3017ed1b4dc4aac21d7405fd667498bf8eba01

The command above is suffixed with the byte 0x01. Trying to understand what is the purpose of this byte? For the URL above, three major steps was used to compute the normalized private key from the curve order for either ed25519 or cv25519. Another person independently made a similar computation and concluded it was unclear what the traceability for the extra 8 byte.

1 Answer 1


All sc_reduce32 does is perform mod l where l = 7237005577332262213973186563042994240857116359379907606001950938285454250989. Byte sequences are little endian.

Your input deefd263cbfed62a3711dd133df3ccbd1c4dc4aac21d7405fd667498bf8ebaa1 is the number 73151987389341079160941681836269938279688779415452276994447379963081137516510, and 73151987389341079160941681836269938279688779415452276994447379963081137516510 mod 7237005577332262213973186563042994240857116359379907606001950938285454250989 is 781931616018457021209816205839995871117615821653200934427870580226595006620, which in little endian bytes is 9ca838c2c31f1fbad7f030b68a3017ed1b4dc4aac21d7405fd667498bf8eba01.

Your result is therefore correct. There are no 'extra' bytes. The input and output are both 32 byte sequences.

  • Question remains unanswered.
    – skaht
    Jan 23, 2020 at 22:58
  • I noticed something. Your output in the previous question 1BA8EBF987466FD05741DC2AAC44D1BED17308AB630F0D7BA1F1FC3C238A89C starts with 1BA..., which in little endian would be ...BA01 (since that output is 31.5 bytes, there is a 0x01). I wonder if it's not converting to little endian since the 4 0 bits on the end are missing. Perhaps I made a mistake in my computation, or failed to notice something.
    – koe
    Jan 23, 2020 at 23:02
  • % echo "obase=16; ibase=10; 781931616018457021209816205839995871117615821653200934427870580226595006620"| bc | rev | dd conv=swab 9CA838C2C31F1FBAD7F030B68A3017ED1B4DC4AAC21D7405FD667498BF8EBA != 9CA838C2C31F1FBAD7F030B68A3017ED1B4DC4AAC21D7405FD667498BF8EBA01
    – skaht
    Jan 23, 2020 at 23:05
  • 1
    @skaht You appear to be asking why 0x01 has been "suffixed". Nothing has been suffixed, that's just what the answer mathematically looks like. If you do sc_reduce32 on a different number you may not see 0x01 at the end of the resulting hex string, depending on the number you start with. All 0x01 means is that the result happens to start with 2^248 as the highest bits set. Since scalars can go up to about 2^252, the result string of hex will not always end with 0x01. If this still doesn't answer your question, please be specific about exactly what isn't clear.
    – knaccc
    Jan 24, 2020 at 1:46
  • 1
    Problem solved. The issue (my bad) was that that endian conversion is very sensitive to having any leading zero hex digits dropped. This was evident from only % echo "obase=10; ibase=16; 01BA8EBF987466FD05741DC2AAC44D1BED17308AB630F0D7BA1F1FC3C238A89C" | bc 78193161601845702120981620583999587111761582165320093442787058022659 converted properly to base10 and 1BA8EBF987466FD05741DC2AAC44D1BED17308AB630F0D7BA1F1FC3C238A89C did not. Thanks for the assistance:-)
    – skaht
    Jan 24, 2020 at 4:45

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.