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.
This commit is contained in:
Frank Denis
2022-11-28 00:34:13 +01:00
committed by GitHub
parent 6097165241
commit 7411be3c9e
2 changed files with 14 additions and 1 deletions

View File

@@ -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 |_| {}
}

View File

@@ -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() };