Expose the elligator map for Curve25519

This is the same as for Edwards25519 without the y coordinate,
since it returns Montgomery coordinates, but it can be confusing
to call the Edwards25519 function while working on the
Curve25519 representation.

New protocols such as CPACE requires the map over Curve25519.
This commit is contained in:
Frank Denis
2026-02-23 23:04:26 +01:00
parent 27ef6e9a9b
commit e8ca9229c8
+22
View File
@@ -101,6 +101,11 @@ pub const Curve25519 = struct {
return try ladder(p, s, 256);
}
/// Elligator2 map for Curve25519.
pub fn elligator2(r: Fe) Curve25519 {
return .{ .x = crypto.ecc.Edwards25519.elligator2(r).x };
}
/// Compute the Curve25519 equivalent to an Edwards25519 point.
///
/// Note that the function doesn't check that the input point is
@@ -145,6 +150,23 @@ test "non-affine edwards25519 to curve25519 projection" {
try std.testing.expectEqualSlices(u8, &xp.toBytes(), &expected);
}
test "elligator2" {
const Fe = Curve25519.Fe;
// RFC 9380 Appendix J.4.2 test vector (curve25519_XMD:SHA-512_ELL2_NU_)
// u = 0x608d892b641f0328523802a6603427c26e55e6f27e71a91a478148d45b5093cd
// Q.x = 0x51125222da5e763d97f3c10fcc92ea6860b9ccbbd2eb1285728f566721c1e65b
const u = Fe.fromBytes(.{
0xcd, 0x93, 0x50, 0x5b, 0xd4, 0x48, 0x81, 0x47, 0x1a, 0xa9, 0x71, 0x7e, 0xf2, 0xe6, 0x55, 0x6e,
0xc2, 0x27, 0x34, 0x60, 0xa6, 0x02, 0x38, 0x52, 0x28, 0x03, 0x1f, 0x64, 0x2b, 0x89, 0x8d, 0x60,
});
const p = Curve25519.elligator2(u);
try std.testing.expectEqual([32]u8{
0x5b, 0xe6, 0xc1, 0x21, 0x67, 0x56, 0x8f, 0x72, 0x85, 0x12, 0xeb, 0xd2, 0xbb, 0xcc, 0xb9, 0x60,
0x68, 0xea, 0x92, 0xcc, 0x0f, 0xc1, 0xf3, 0x97, 0x3d, 0x76, 0x5e, 0xda, 0x22, 0x52, 0x12, 0x51,
}, p.toBytes());
}
test "small order check" {
var s: [32]u8 = [_]u8{1} ++ [_]u8{0} ** 31;
const small_order_ss: [7][32]u8 = .{