From 7411be3c9e6d169108456f03b3cbb9b476ee7498 Mon Sep 17 00:00:00 2001 From: Frank Denis <124872+jedisct1@users.noreply.github.com> Date: Mon, 28 Nov 2022 00:34:13 +0100 Subject: [PATCH] std.crypto.edwards25519: add a rejectLowOrder() function (#13668) Does what the name says: rejects generators of low-order groups. `clearCofactor()` was previously used to do it, but for e.g. cofactored signature verification, we don't need the result of an actual multiplication. Only check that we didn't end up with a low-order point, which is a faster operation. --- lib/std/crypto/25519/ed25519.zig | 2 +- lib/std/crypto/25519/edwards25519.zig | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/std/crypto/25519/ed25519.zig b/lib/std/crypto/25519/ed25519.zig index 149191040a7bb685d2919bdd275495263485ce78..7d136fc12df4c4da9d54fbb2a8ae4ed03c8dce64 100644 --- a/lib/std/crypto/25519/ed25519.zig +++ b/lib/std/crypto/25519/ed25519.zig @@ -181,7 +181,7 @@ pub const Ed25519 = struct { const hram = Curve.scalar.reduce64(hram64); const sb_ah = try Curve.basePoint.mulDoubleBasePublic(self.s, self.a.neg(), hram); - if (self.expected_r.sub(sb_ah).clearCofactor().rejectIdentity()) |_| { + if (self.expected_r.sub(sb_ah).rejectLowOrder()) { return error.SignatureVerificationFailed; } else |_| {} } diff --git a/lib/std/crypto/25519/edwards25519.zig b/lib/std/crypto/25519/edwards25519.zig index f7b07738a2fde35387c8553e80cb2f64f9ea278c..840f4b67d586c1cefd858f407063b8fb40128cec 100644 --- a/lib/std/crypto/25519/edwards25519.zig +++ b/lib/std/crypto/25519/edwards25519.zig @@ -83,6 +83,19 @@ pub const Edwards25519 = struct { return p.dbl().dbl().dbl(); } + /// Check that the point does not generate a low-order group. + /// Return a `WeakPublicKey` error if it does. + pub fn rejectLowOrder(p: Edwards25519) WeakPublicKeyError!void { + const zi = p.z.invert(); + const x = p.x.mul(zi); + const y = p.y.mul(zi); + const x_neg = x.neg(); + const iy = Fe.sqrtm1.mul(y); + if (x.isZero() or y.isZero() or iy.equivalent(x) or iy.equivalent(x_neg)) { + return error.WeakPublicKey; + } + } + /// Flip the sign of the X coordinate. pub inline fn neg(p: Edwards25519) Edwards25519 { return .{ .x = p.x.neg(), .y = p.y, .z = p.z, .t = p.t.neg() }; -- 2.54.0