Known Elligator 2 Implementations
These are the implementation we know about as of 2022/06. Please contact us to have your implementation added to this list.
Complete implementations
They provide a complete implementation, suitable for key exchange.
libdecaf Implements a variant of Elligator for ristretto255 (based on Curve255) and ristretto448 (based on Curve448). Implementers seeking to implement Elligator for the Ristretto group may want to follow libdecaf instead. This would promote compatibility, avoid fragmentation, and would be just as safe (The libdecaf author basically invented Elligator 2).
Monocypher implements Elligator 2 for Curve25519. It is designed to be compatible with X25519. The map uses Zu = 2, non-negative field elements are the set {0, 1, … (p−1)/2}, and the inverse map always generate positive representatives (and pad the top two most significant bits with random data).
GNUnet implements Elligator 2 for X25519. It is very close to Monocypher and Kleshni, but bits are padded and the special public key derivation is implemented. The functionality is exposed through a RFC9180-style KEM interface. Elligator is used to obfuscate transport-level key exchanges and authentications of GNUnet peers.
Hash-to-Point implementations
These only implement the direct map (without necessarily exposing it), so random numbers can be mapped to curve points whose discrete logarithm is unknown (this is most useful for Password Authenticated Key Agreement).
libsodium uses the Elligator 2 direct map for Ed25519 and ristretto255. For Ed25519 it follows the Map-to-Curve procedure outlined in the Hash to curve RFC draft. For ristretto255 it only implements this mapping, which is indistinguishable from a random oracle.
Curve25519-Dalek uses the Elligator 2 direct map for Ed25519 and ristretto255. It uses the same strategies as libsodium.
Incomplete implementations
Kleshni implements Elligator 2 for Curve25519. It is very close to Monocypher. The only difference is that the direct map does not ignore the top two bits. Instead all 256 bits are interpreted and reduced modulo p. However, as of 2022/06:
- The inverse map does not pad the representative at all, so the top two bits are always zero. To pad those bits in a way that is compatible with its direct map we need to randomly negate the representative then randomly add p.
- The special public key derivation required to use the inverse map safely is missing.