# Key clamping in curve25519 not evident in generated key's binary representation

I understand with curve25519 that the private key for secret.box is clamped...

I understand that this clamping process to clear the lower 3 bits in order to ensure the key is a multiple of 8, ensuring it's part of the right cyclic subgroup.

However, as I generate example keyPairs using sodium such as:

a67e2d949d00606d2b6d0d9114d3ee273f118a078151c7aad2b55694ea18bb39 // 1010011001111110001011011001010010011101000000000110000001101101001010110110110100001101100100010001010011010011111011100010011100111111000100011000101000000111100000010101000111000111101010101101001010110101010101101001010011101010000110001011101100111001


or

b2c80def0dc392671e5143e9804c1083a39c751eec7348383eb586d708b374cc // 1011001011001000000011011110111100001101110000111001001001100111000111100101000101000011111010011000000001001100000100001000001110100011100111000111010100011110111011000111001101001000001110000011111010110101100001101101011100001000101100110111010011001100


I noticed that despite being able to positively confirm they are part of the multiple of 8 subgroup, their binary representation does not have the lower three bits cleared...

So as you can see above, the binary representation of these random private keys doesn't have 000 for the lowest three bits. Yet when I check in SageMath, I can confirm both of these keys are multiples of 8.

Update: I generated the keys using the libSodium->SecretBox->KeyPair()...

Which internally calls the clamping/scalar multiplication.

I also verified that despite not ending in three zeros (000) - the private keys are always of order 7237005577332262213973186563042994240857116359379907606001950938285454250989 and as such are of the correct subgroup.

Any idea why?

• Not clear how did you generate the pairs? – kelalaka Nov 22 '19 at 11:27
• @kelalaka updated my question... – Woodstock Nov 22 '19 at 11:33

• Writing the curve order as $8n$ with $n$ prime; the base point has order $n$, so if you multiply it by some $k \neq 0 \bmod p$ the resulting point will also have order $n$. This does not imply that $k$ is a multiple of 8. The clamping protects ECDH when multiplying with some arbitrary point provided by the other party which may have order different than $n$. – Conrado Nov 22 '19 at 11:41
• @Woodstock Correct. If you really don't want clampling to happen, this is still an option (crypto_scalarmult_ed25519_noclamp() and crypto_scalarmult_ed25519_base_noclamp()), but these functions will check that the public key is on the main subgroup, which is slower than clamping. Using the Ristretto encoding may be a better option. – Frank Denis Nov 22 '19 at 21:27