Trying to get an intuition about the hashing that Monero is doing.

Some definitions:

Let P represent a point on the Ed25519 curve that's also a part of the group.

Let H represent a hash function.

Let E(P) be the function that encodes P into a 32-byte repesentation.

Let D(b) be the function that decodes a 32-byte representation to a point on the curve.

The Monero source code for hash_to_ec function, which maps an Ed25519 Point to another Ed25519 Point does something like this:

H_p(P) = 8*D(H(E(P)))

(see https://github.com/monero-project/monero/blob/1a4298685aa9e694bc555ae69be59d14d3790465/src/crypto/crypto.cpp#L245)

Why the 8?

Also, the derivation_to_scalar function, which maps an Ed25519 Point to a scalar does something like this:

H_s(P) = H(H(8*E(P)) || output_index)

see https://github.com/monero-project/monero/blob/1a4298685aa9e694bc555ae69be59d14d3790465/src/crypto/crypto.cpp#L139 and https://github.com/monero-project/monero/blob/1a4298685aa9e694bc555ae69be59d14d3790465/src/crypto/crypto.cpp#L154

I can understand concatenating the output_index, but I don't understand why the multiply by 8 is there.

Can someone shed light on either/both of these constructions? The only guess I have is that somehow, multiplying by 8 after hashing guarantees the resulting point is in the Group.

These multiplications are trying to address a similar problem discovered in the key image exploit - small order subgroup issues.


The derivation_to_scalar issue is easier to describe; it is listed on Daniel Bernstein's page about twist security. If an attacker provides a small order point (i.e. a point whose group has 8 members) in tx_extra for the transaction public key, then sends a small amount of XMR to each of those points in the group, whichever output is spent by the user will tell the attacker (and any "public" viewers of the chain that know where to look) the lower 3-bits of the secret view key. Mutiplying by 8 guarantees that the result of the ECDH step will always be in the main group, and therefore will never leak anything about the secret key.

Alternatively, curve25519 sets the lower 3-bits of the key (scalar) to zero. This reduces the security by 3-bits while simultaneously making the key a multiple of 8. All scalar point multiplications with this type of key will therefore result on the primary group.


hash_to_ec is a little different - it converts a 32-byte scalar to a y-coordinate then "recovers" the x-coordinate based on the ED25519 curve. So the point recovered might be on the ED25519 curve, but not the primary ED25519 group. Multiplying by 8 gets the "nearest" point in the primary group.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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