authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-05-28 21:05:46+02:00
committergravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-07-05 12:21:43+02:00
log33155e3504e2478f3ac9fc00f20bf698484119c0
tree53e119282a6a353d9bb7b4f292f4372db5610042
parenteb2a1bb0d04532c84c042eaad1c3ee092c8c8a23

crypto.edwards25519: reject order-2L points

This is a variant of a bug that was originally fixed in libsodium 1.0.21 which was incidentally found by writing Zig code. rejectUnexpectedSubgroup() should return an error for points of order 2L, i.e. the coset T + ⟨G⟩ where T is the order-2 element.

1 files changed, 6 insertions(+), 1 deletions(-)

lib/std/crypto/25519/edwards25519.zig+6-1
......@@ -115,7 +115,7 @@ pub const Edwards25519 = struct {
115115 .add(_1010011)).shift(9).add(_11110101))).shift(7).add(_1100111)).shift(9).add(_11110101).shift(11)
116116 .add(_10111101)).shift(8).add(_11100111)).shift(9))).shift(6).add(_1011)).shift(14).add(_10010011).shift(10)
117117 .add(_1100011)).shift(9).add(_10010111)).shift(10))).shift(8).add(_11010011)).shift(8).add(_11101101);
118 q.rejectIdentity() catch return;
118 if (q.x.isZero() and q.y.equivalent(q.z)) return;
119119 return error.UnexpectedSubgroup;
120120 }
121121
......@@ -634,4 +634,9 @@ test "subgroup check" {
634634 _ = try std.fmt.hexToBytes(&bogus, "4dc95e3c28d78c48a60531525e6327e259b7ba0d2f5c81b694052c766a14b625");
635635 const p = try Edwards25519.fromBytes(bogus);
636636 try std.testing.expectError(error.UnexpectedSubgroup, p.rejectUnexpectedSubgroup());
637
638 var torsion2L: [Edwards25519.encoded_length]u8 = undefined;
639 _ = try std.fmt.hexToBytes(&torsion2L, "9599999999999999999999999999999999999999999999999999999999999999");
640 const p2L = try Edwards25519.fromBytes(torsion2L);
641 try std.testing.expectError(error.UnexpectedSubgroup, p2L.rejectUnexpectedSubgroup());
637642}