| ... | @@ -101,6 +101,11 @@ pub const Curve25519 = struct { | ... | @@ -101,6 +101,11 @@ pub const Curve25519 = struct { |
| 101 | return try ladder(p, s, 256); | 101 | return try ladder(p, s, 256); |
| 102 | } | 102 | } |
| 103 | | 103 | |
| | 104 | /// Elligator2 map for Curve25519. |
| | 105 | pub fn elligator2(r: Fe) Curve25519 { |
| | 106 | return .{ .x = crypto.ecc.Edwards25519.elligator2(r).x }; |
| | 107 | } |
| | 108 | |
| 104 | /// Compute the Curve25519 equivalent to an Edwards25519 point. | 109 | /// Compute the Curve25519 equivalent to an Edwards25519 point. |
| 105 | /// | 110 | /// |
| 106 | /// Note that the function doesn't check that the input point is | 111 | /// Note that the function doesn't check that the input point is |
| ... | @@ -145,6 +150,23 @@ test "non-affine edwards25519 to curve25519 projection" { | ... | @@ -145,6 +150,23 @@ test "non-affine edwards25519 to curve25519 projection" { |
| 145 | try std.testing.expectEqualSlices(u8, &xp.toBytes(), &expected); | 150 | try std.testing.expectEqualSlices(u8, &xp.toBytes(), &expected); |
| 146 | } | 151 | } |
| 147 | | 152 | |
| | 153 | test "elligator2" { |
| | 154 | const Fe = Curve25519.Fe; |
| | 155 | |
| | 156 | // RFC 9380 Appendix J.4.2 test vector (curve25519_XMD:SHA-512_ELL2_NU_) |
| | 157 | // u = 0x608d892b641f0328523802a6603427c26e55e6f27e71a91a478148d45b5093cd |
| | 158 | // Q.x = 0x51125222da5e763d97f3c10fcc92ea6860b9ccbbd2eb1285728f566721c1e65b |
| | 159 | const u = Fe.fromBytes(.{ |
| | 160 | 0xcd, 0x93, 0x50, 0x5b, 0xd4, 0x48, 0x81, 0x47, 0x1a, 0xa9, 0x71, 0x7e, 0xf2, 0xe6, 0x55, 0x6e, |
| | 161 | 0xc2, 0x27, 0x34, 0x60, 0xa6, 0x02, 0x38, 0x52, 0x28, 0x03, 0x1f, 0x64, 0x2b, 0x89, 0x8d, 0x60, |
| | 162 | }); |
| | 163 | const p = Curve25519.elligator2(u); |
| | 164 | try std.testing.expectEqual([32]u8{ |
| | 165 | 0x5b, 0xe6, 0xc1, 0x21, 0x67, 0x56, 0x8f, 0x72, 0x85, 0x12, 0xeb, 0xd2, 0xbb, 0xcc, 0xb9, 0x60, |
| | 166 | 0x68, 0xea, 0x92, 0xcc, 0x0f, 0xc1, 0xf3, 0x97, 0x3d, 0x76, 0x5e, 0xda, 0x22, 0x52, 0x12, 0x51, |
| | 167 | }, p.toBytes()); |
| | 168 | } |
| | 169 | |
| 148 | test "small order check" { | 170 | test "small order check" { |
| 149 | var s: [32]u8 = [_]u8{1} ++ [_]u8{0} ** 31; | 171 | var s: [32]u8 = [_]u8{1} ++ [_]u8{0} ** 31; |
| 150 | const small_order_ss: [7][32]u8 = .{ | 172 | const small_order_ss: [7][32]u8 = .{ |