diff --git a/lib/std/crypto/25519/curve25519.zig b/lib/std/crypto/25519/curve25519.zig index b3e014b6d1..9980c152eb 100644 --- a/lib/std/crypto/25519/curve25519.zig +++ b/lib/std/crypto/25519/curve25519.zig @@ -19,10 +19,8 @@ pub const Curve25519 = struct { return p.x.toBytes(); } - /// Return the Curve25519 base point. - pub inline fn basePoint() Curve25519 { - return .{ .x = Fe.curve25519BasePoint }; - } + /// The Curve25519 base point. + pub const basePoint = Curve25519{ .x = Fe.curve25519BasePoint }; /// Check that the encoding of a Curve25519 point is canonical. pub fn rejectNonCanonical(s: [32]u8) !void { @@ -103,7 +101,7 @@ pub const Curve25519 = struct { test "curve25519" { var s = [32]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 }; - const p = try Curve25519.basePoint().clampedMul(s); + const p = try Curve25519.basePoint.clampedMul(s); try p.rejectIdentity(); var buf: [128]u8 = undefined; std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{p.toBytes()}), "E6F2A4D1C28EE5C7AD0329268255A468AD407D2672824C0C0EB30EA6EF450145"); diff --git a/lib/std/crypto/25519/ed25519.zig b/lib/std/crypto/25519/ed25519.zig index 669bb94480..eb004d2607 100644 --- a/lib/std/crypto/25519/ed25519.zig +++ b/lib/std/crypto/25519/ed25519.zig @@ -19,12 +19,19 @@ pub const Ed25519 = struct { pub const noise_length = 32; /// Derive a key pair from a secret seed. + /// + /// As in RFC 8032, an Ed25519 public key is generated by hashing + /// the secret key using the SHA-512 function, and interpreting the + /// bit-swapped, clamped lower-half of the output as the secret scalar. + /// + /// For this reason, an EdDSA secret key is commonly called a seed, + /// from which the actual secret is derived. pub fn createKeyPair(seed: [seed_length]u8) ![keypair_length]u8 { var az: [Sha512.digest_length]u8 = undefined; var h = Sha512.init(); h.update(&seed); h.final(&az); - const p = try Curve.basePoint().clampedMul(az[0..32].*); + const p = try Curve.basePoint.clampedMul(az[0..32].*); var keypair: [keypair_length]u8 = undefined; mem.copy(u8, &keypair, &seed); mem.copy(u8, keypair[seed_length..], &p.toBytes()); @@ -57,7 +64,7 @@ pub const Ed25519 = struct { var nonce64: [64]u8 = undefined; h.final(&nonce64); const nonce = Curve.scalar.reduce64(nonce64); - const r = try Curve.basePoint().mul(nonce); + const r = try Curve.basePoint.mul(nonce); var sig: [signature_length]u8 = undefined; mem.copy(u8, sig[0..32], &r.toBytes()); @@ -95,7 +102,7 @@ pub const Ed25519 = struct { const hram = Curve.scalar.reduce64(hram64); const p = try a.neg().mul(hram); - const check = (try Curve.basePoint().mul(s.*)).add(p).toBytes(); + const check = (try Curve.basePoint.mul(s.*)).add(p).toBytes(); if (mem.eql(u8, &check, r) == false) { return error.InvalidSignature; } diff --git a/lib/std/crypto/25519/edwards25519.zig b/lib/std/crypto/25519/edwards25519.zig index a7044794b2..a65e1dfc11 100644 --- a/lib/std/crypto/25519/edwards25519.zig +++ b/lib/std/crypto/25519/edwards25519.zig @@ -50,20 +50,16 @@ pub const Edwards25519 = struct { return Fe.rejectNonCanonical(s, true); } - /// Return the Edwards25519 base point. - pub inline fn basePoint() Edwards25519 { - return .{ - .x = Fe{ .limbs = .{ 3990542415680775, 3398198340507945, 4322667446711068, 2814063955482877, 2839572215813860 } }, - .y = Fe{ .limbs = .{ 1801439850948184, 1351079888211148, 450359962737049, 900719925474099, 1801439850948198 } }, - .z = Fe.one, - .t = Fe{ .limbs = .{ 1841354044333475, 16398895984059, 755974180946558, 900171276175154, 1821297809914039 } }, - .is_base = true, - }; - } + /// The edwards25519 base point. + pub const basePoint = Edwards25519{ + .x = Fe{ .limbs = .{ 3990542415680775, 3398198340507945, 4322667446711068, 2814063955482877, 2839572215813860 } }, + .y = Fe{ .limbs = .{ 1801439850948184, 1351079888211148, 450359962737049, 900719925474099, 1801439850948198 } }, + .z = Fe.one, + .t = Fe{ .limbs = .{ 1841354044333475, 16398895984059, 755974180946558, 900171276175154, 1821297809914039 } }, + .is_base = true, + }; - inline fn identityElement() Edwards25519 { - return .{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero }; - } + const identityElement = Edwards25519{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero }; /// Reject the neutral element. pub fn rejectIdentity(p: Edwards25519) !void { @@ -121,16 +117,16 @@ pub const Edwards25519 = struct { } inline fn pcSelect(pc: [16]Edwards25519, b: u8) Edwards25519 { - var t = Edwards25519.identityElement(); + var t = Edwards25519.identityElement; comptime var i: u8 = 0; inline while (i < 16) : (i += 1) { - t.cMov(pc[i], ((@as(usize, (b ^ i)) -% 1) >> 8) & 1); + t.cMov(pc[i], ((@as(usize, b ^ i) -% 1) >> 8) & 1); } return t; } fn pcMul(pc: [16]Edwards25519, s: [32]u8) !Edwards25519 { - var q = Edwards25519.identityElement(); + var q = Edwards25519.identityElement; var pos: usize = 252; while (true) : (pos -= 4) { q = q.dbl().dbl().dbl().dbl(); @@ -144,7 +140,7 @@ pub const Edwards25519 = struct { fn precompute(p: Edwards25519) [16]Edwards25519 { var pc: [16]Edwards25519 = undefined; - pc[0] = Edwards25519.identityElement(); + pc[0] = Edwards25519.identityElement; pc[1] = p; var i: usize = 2; while (i < 16) : (i += 1) { @@ -153,11 +149,14 @@ pub const Edwards25519 = struct { return pc; } - fn _mul(p: Edwards25519, s: [32]u8) !Edwards25519 { + /// Multiply an Edwards25519 point by a scalar without clamping it. + /// Return error.WeakPublicKey if the resulting point is + /// the identity element. + pub fn mul(p: Edwards25519, s: [32]u8) !Edwards25519 { var pc: [16]Edwards25519 = undefined; if (p.is_base) { @setEvalBranchQuota(10000); - pc = comptime precompute(Edwards25519.basePoint()); + pc = comptime precompute(Edwards25519.basePoint); } else { pc = precompute(p); pc[4].rejectIdentity() catch |_| return error.WeakPublicKey; @@ -174,20 +173,13 @@ pub const Edwards25519 = struct { pub fn clampedMul(p: Edwards25519, s: [32]u8) !Edwards25519 { var t: [32]u8 = s; scalar.clamp(&t); - return _mul(p, t); - } - - /// Multiply an Edwards25519 point by a scalar without clamping it. - /// Return error.WeakPublicKey if the resulting point is - /// the identity element. - pub fn mul(p: Edwards25519, s: [32]u8) !Edwards25519 { - return _mul(p, s); + return mul(p, t); } }; test "edwards25519 packing/unpacking" { const s = [_]u8{170} ++ [_]u8{0} ** 31; - var b = Edwards25519.basePoint(); + var b = Edwards25519.basePoint; const pk = try b.mul(s); var buf: [128]u8 = undefined; std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{pk.toBytes()}), "074BC7E0FCBD587FDBC0969444245FADC562809C8F6E97E949AF62484B5B81A6"); diff --git a/lib/std/crypto/25519/ristretto255.zig b/lib/std/crypto/25519/ristretto255.zig index 0bb8e1c92a..21b305f89d 100644 --- a/lib/std/crypto/25519/ristretto255.zig +++ b/lib/std/crypto/25519/ristretto255.zig @@ -43,10 +43,8 @@ pub const Ristretto255 = struct { return p.p.rejectIdentity(); } - /// Return the base point (Ristretto is a curve in desguise). - pub inline fn basePoint() Ristretto255 { - return .{ .p = Curve.basePoint() }; - } + /// The base point (Ristretto is a curve in desguise). + pub const basePoint = Ristretto255{ .p = Curve.basePoint }; /// Decode a Ristretto255 representative. pub fn fromBytes(s: [32]u8) !Ristretto255 { @@ -130,7 +128,7 @@ pub const Ristretto255 = struct { }; test "ristretto255" { - const p = Ristretto255.basePoint(); + const p = Ristretto255.basePoint; var buf: [256]u8 = undefined; std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{p.toBytes()}), "E2F2AE0A6ABC4E71A884A961C500515F58E30B6AA582DD8DB6A65945E08D2D76"); diff --git a/lib/std/crypto/25519/x25519.zig b/lib/std/crypto/25519/x25519.zig index ac88d40952..4b5a8b8482 100644 --- a/lib/std/crypto/25519/x25519.zig +++ b/lib/std/crypto/25519/x25519.zig @@ -17,7 +17,7 @@ pub const X25519 = struct { std.debug.assert(public_key.len >= minimum_key_length); var s: [32]u8 = undefined; mem.copy(u8, &s, private_key[0..32]); - if (Curve.basePoint().clampedMul(s)) |q| { + if (Curve.basePoint.clampedMul(s)) |q| { mem.copy(u8, public_key, q.toBytes()[0..]); return true; } else |_| { @@ -52,7 +52,7 @@ test "x25519 public key calculation from secret key" { try fmt.hexToBytes(sk[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166"); try fmt.hexToBytes(pk_expected[0..], "f1814f0e8ff1043d8a44d25babff3cedcae6c22c3edaa48f857ae70de2baae50"); std.testing.expect(X25519.createPublicKey(pk_calculated[0..], &sk)); - std.testing.expect(std.mem.eql(u8, &pk_calculated, &pk_expected)); + std.testing.expectEqual(pk_calculated, pk_expected); } test "x25519 rfc7748 vector1" { @@ -64,7 +64,7 @@ test "x25519 rfc7748 vector1" { var output: [32]u8 = undefined; std.testing.expect(X25519.create(output[0..], secret_key[0..], public_key[0..])); - std.testing.expect(std.mem.eql(u8, &output, expected_output[0..])); + std.testing.expectEqual(output, expected_output); } test "x25519 rfc7748 vector2" { @@ -76,7 +76,7 @@ test "x25519 rfc7748 vector2" { var output: [32]u8 = undefined; std.testing.expect(X25519.create(output[0..], secret_key[0..], public_key[0..])); - std.testing.expect(std.mem.eql(u8, &output, expected_output[0..])); + std.testing.expectEqual(output, expected_output); } test "x25519 rfc7748 one iteration" { @@ -91,11 +91,11 @@ test "x25519 rfc7748 one iteration" { var output: [32]u8 = undefined; std.testing.expect(X25519.create(output[0..], &k, &u)); - std.mem.copy(u8, u[0..], k[0..]); - std.mem.copy(u8, k[0..], output[0..]); + mem.copy(u8, u[0..], k[0..]); + mem.copy(u8, k[0..], output[0..]); } - std.testing.expect(std.mem.eql(u8, k[0..], expected_output[0..])); + std.testing.expectEqual(k, expected_output); } test "x25519 rfc7748 1,000 iterations" { @@ -115,11 +115,11 @@ test "x25519 rfc7748 1,000 iterations" { var output: [32]u8 = undefined; std.testing.expect(X25519.create(output[0..], &k, &u)); - std.mem.copy(u8, u[0..], k[0..]); - std.mem.copy(u8, k[0..], output[0..]); + mem.copy(u8, u[0..], k[0..]); + mem.copy(u8, k[0..], output[0..]); } - std.testing.expect(std.mem.eql(u8, k[0..], expected_output)); + std.testing.expectEqual(k, expected_output); } test "x25519 rfc7748 1,000,000 iterations" { @@ -138,9 +138,9 @@ test "x25519 rfc7748 1,000,000 iterations" { var output: [32]u8 = undefined; std.testing.expect(X25519.create(output[0..], &k, &u)); - std.mem.copy(u8, u[0..], k[0..]); - std.mem.copy(u8, k[0..], output[0..]); + mem.copy(u8, u[0..], k[0..]); + mem.copy(u8, k[0..], output[0..]); } - std.testing.expect(std.mem.eql(u8, k[0..], expected_output)); + std.testing.expectEqual(k[0..], expected_output); }