Commit 7411be3c9e

Frank Denis <124872+jedisct1@users.noreply.github.com>
2022-11-28 00:34:13
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.
1 parent 6097165
Changed files (2)
lib
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 |_| {}
         }
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() };