diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/std/crypto/25519/curve25519.zig | 5 | ||||
| -rw-r--r-- | lib/std/crypto/25519/ed25519.zig | 9 | ||||
| -rw-r--r-- | lib/std/crypto/25519/edwards25519.zig | 24 |
3 files changed, 34 insertions, 4 deletions
diff --git a/lib/std/crypto/25519/curve25519.zig b/lib/std/crypto/25519/curve25519.zig index 94490f674c..7f180eac2f 100644 --- a/lib/std/crypto/25519/curve25519.zig +++ b/lib/std/crypto/25519/curve25519.zig @@ -39,6 +39,11 @@ pub const Curve25519 = struct { } } + /// Multiply a point by the cofactor + pub fn clearCofactor(p: Edwards25519) Edwards25519 { + return p.dbl().dbl().dbl(); + } + fn ladder(p: Curve25519, s: [32]u8, comptime bits: usize) !Curve25519 { var x1 = p.x; var x2 = Fe.one; diff --git a/lib/std/crypto/25519/ed25519.zig b/lib/std/crypto/25519/ed25519.zig index 9993afb6d2..784ba62de0 100644 --- a/lib/std/crypto/25519/ed25519.zig +++ b/lib/std/crypto/25519/ed25519.zig @@ -97,6 +97,7 @@ pub const Ed25519 = struct { try Curve.rejectNonCanonical(public_key); const a = try Curve.fromBytes(public_key); try a.rejectIdentity(); + const expected_r = try Curve.fromBytes(r.*); var h = Sha512.init(.{}); h.update(r); @@ -106,11 +107,11 @@ pub const Ed25519 = struct { h.final(&hram64); const hram = Curve.scalar.reduce64(hram64); - const p = try a.neg().mul(hram); - const check = (try Curve.basePoint.mul(s.*)).add(p).toBytes(); - if (mem.eql(u8, &check, r) == false) { + const ah = try a.neg().mul(hram); + const sb_ah = (try Curve.basePoint.mul(s.*)).add(ah); + if (expected_r.sub(sb_ah).clearCofactor().rejectIdentity()) |_| { return error.InvalidSignature; - } + } else |_| {} } }; diff --git a/lib/std/crypto/25519/edwards25519.zig b/lib/std/crypto/25519/edwards25519.zig index 176e5337da..f98774542f 100644 --- a/lib/std/crypto/25519/edwards25519.zig +++ b/lib/std/crypto/25519/edwards25519.zig @@ -73,6 +73,11 @@ pub const Edwards25519 = struct { } } + /// Multiply a point by the cofactor + pub fn clearCofactor(p: Edwards25519) Edwards25519 { + return p.dbl().dbl().dbl(); + } + /// 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() }; @@ -114,6 +119,11 @@ pub const Edwards25519 = struct { }; } + /// Substract two Edwards25519 points. + pub fn sub(p: Edwards25519, q: Edwards25519) Edwards25519 { + return p.add(q.neg()); + } + inline fn cMov(p: *Edwards25519, a: Edwards25519, c: u64) void { p.x.cMov(a.x, c); p.y.cMov(a.y, c); @@ -217,3 +227,17 @@ test "edwards25519 packing/unpacking" { std.testing.expectError(error.WeakPublicKey, small_p.mul(s)); } } + +test "edwards25519 point addition/substraction" { + var s1: [32]u8 = undefined; + var s2: [32]u8 = undefined; + try std.crypto.randomBytes(&s1); + try std.crypto.randomBytes(&s2); + const p = try Edwards25519.basePoint.clampedMul(s1); + const q = try Edwards25519.basePoint.clampedMul(s2); + const r = p.add(q).add(q).sub(q).sub(q); + try r.rejectIdentity(); + std.testing.expectError(error.IdentityElement, r.sub(p).rejectIdentity()); + std.testing.expectError(error.IdentityElement, p.sub(p).rejectIdentity()); + std.testing.expectError(error.IdentityElement, p.sub(q).add(q).sub(p).rejectIdentity()); +} |
