| author | |
| committer | |
| log | bcef123d902b9d1d8a27b0414932b1b92f6f1a7e |
| tree | 22ad97205c0a529cc5d832ba21ec709d11442843 |
| parent | 263c44473896597346bc244d82a2b436d7d2da02 |
5 files changed, 49 insertions(+), 54 deletions(-)
lib/std/crypto/25519/curve25519.zig+3-5| ... | ... | @@ -19,10 +19,8 @@ pub const Curve25519 = struct { |
| 19 | 19 | return p.x.toBytes(); |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | /// Return the Curve25519 base point. | |
| 23 | pub inline fn basePoint() Curve25519 { | |
| 24 | return .{ .x = Fe.curve25519BasePoint }; | |
| 25 | } | |
| 22 | /// The Curve25519 base point. | |
| 23 | pub const basePoint = Curve25519{ .x = Fe.curve25519BasePoint }; | |
| 26 | 24 | |
| 27 | 25 | /// Check that the encoding of a Curve25519 point is canonical. |
| 28 | 26 | pub fn rejectNonCanonical(s: [32]u8) !void { |
| ... | ... | @@ -103,7 +101,7 @@ pub const Curve25519 = struct { |
| 103 | 101 | |
| 104 | 102 | test "curve25519" { |
| 105 | 103 | 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 }; |
| 106 | const p = try Curve25519.basePoint().clampedMul(s); | |
| 104 | const p = try Curve25519.basePoint.clampedMul(s); | |
| 107 | 105 | try p.rejectIdentity(); |
| 108 | 106 | var buf: [128]u8 = undefined; |
| 109 | 107 | std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{p.toBytes()}), "E6F2A4D1C28EE5C7AD0329268255A468AD407D2672824C0C0EB30EA6EF450145"); |
lib/std/crypto/25519/ed25519.zig+10-3| ... | ... | @@ -19,12 +19,19 @@ pub const Ed25519 = struct { |
| 19 | 19 | pub const noise_length = 32; |
| 20 | 20 | |
| 21 | 21 | /// Derive a key pair from a secret seed. |
| 22 | /// | |
| 23 | /// As in RFC 8032, an Ed25519 public key is generated by hashing | |
| 24 | /// the secret key using the SHA-512 function, and interpreting the | |
| 25 | /// bit-swapped, clamped lower-half of the output as the secret scalar. | |
| 26 | /// | |
| 27 | /// For this reason, an EdDSA secret key is commonly called a seed, | |
| 28 | /// from which the actual secret is derived. | |
| 22 | 29 | pub fn createKeyPair(seed: [seed_length]u8) ![keypair_length]u8 { |
| 23 | 30 | var az: [Sha512.digest_length]u8 = undefined; |
| 24 | 31 | var h = Sha512.init(); |
| 25 | 32 | h.update(&seed); |
| 26 | 33 | h.final(&az); |
| 27 | const p = try Curve.basePoint().clampedMul(az[0..32].*); | |
| 34 | const p = try Curve.basePoint.clampedMul(az[0..32].*); | |
| 28 | 35 | var keypair: [keypair_length]u8 = undefined; |
| 29 | 36 | mem.copy(u8, &keypair, &seed); |
| 30 | 37 | mem.copy(u8, keypair[seed_length..], &p.toBytes()); |
| ... | ... | @@ -57,7 +64,7 @@ pub const Ed25519 = struct { |
| 57 | 64 | var nonce64: [64]u8 = undefined; |
| 58 | 65 | h.final(&nonce64); |
| 59 | 66 | const nonce = Curve.scalar.reduce64(nonce64); |
| 60 | const r = try Curve.basePoint().mul(nonce); | |
| 67 | const r = try Curve.basePoint.mul(nonce); | |
| 61 | 68 | |
| 62 | 69 | var sig: [signature_length]u8 = undefined; |
| 63 | 70 | mem.copy(u8, sig[0..32], &r.toBytes()); |
| ... | ... | @@ -95,7 +102,7 @@ pub const Ed25519 = struct { |
| 95 | 102 | const hram = Curve.scalar.reduce64(hram64); |
| 96 | 103 | |
| 97 | 104 | const p = try a.neg().mul(hram); |
| 98 | const check = (try Curve.basePoint().mul(s.*)).add(p).toBytes(); | |
| 105 | const check = (try Curve.basePoint.mul(s.*)).add(p).toBytes(); | |
| 99 | 106 | if (mem.eql(u8, &check, r) == false) { |
| 100 | 107 | return error.InvalidSignature; |
| 101 | 108 | } |
lib/std/crypto/25519/edwards25519.zig+20-28| ... | ... | @@ -50,20 +50,16 @@ pub const Edwards25519 = struct { |
| 50 | 50 | return Fe.rejectNonCanonical(s, true); |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | /// Return the Edwards25519 base point. | |
| 54 | pub inline fn basePoint() Edwards25519 { | |
| 55 | return .{ | |
| 56 | .x = Fe{ .limbs = .{ 3990542415680775, 3398198340507945, 4322667446711068, 2814063955482877, 2839572215813860 } }, | |
| 57 | .y = Fe{ .limbs = .{ 1801439850948184, 1351079888211148, 450359962737049, 900719925474099, 1801439850948198 } }, | |
| 58 | .z = Fe.one, | |
| 59 | .t = Fe{ .limbs = .{ 1841354044333475, 16398895984059, 755974180946558, 900171276175154, 1821297809914039 } }, | |
| 60 | .is_base = true, | |
| 61 | }; | |
| 62 | } | |
| 53 | /// The edwards25519 base point. | |
| 54 | pub const basePoint = Edwards25519{ | |
| 55 | .x = Fe{ .limbs = .{ 3990542415680775, 3398198340507945, 4322667446711068, 2814063955482877, 2839572215813860 } }, | |
| 56 | .y = Fe{ .limbs = .{ 1801439850948184, 1351079888211148, 450359962737049, 900719925474099, 1801439850948198 } }, | |
| 57 | .z = Fe.one, | |
| 58 | .t = Fe{ .limbs = .{ 1841354044333475, 16398895984059, 755974180946558, 900171276175154, 1821297809914039 } }, | |
| 59 | .is_base = true, | |
| 60 | }; | |
| 63 | 61 | |
| 64 | inline fn identityElement() Edwards25519 { | |
| 65 | return .{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero }; | |
| 66 | } | |
| 62 | const identityElement = Edwards25519{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero }; | |
| 67 | 63 | |
| 68 | 64 | /// Reject the neutral element. |
| 69 | 65 | pub fn rejectIdentity(p: Edwards25519) !void { |
| ... | ... | @@ -121,16 +117,16 @@ pub const Edwards25519 = struct { |
| 121 | 117 | } |
| 122 | 118 | |
| 123 | 119 | inline fn pcSelect(pc: [16]Edwards25519, b: u8) Edwards25519 { |
| 124 | var t = Edwards25519.identityElement(); | |
| 120 | var t = Edwards25519.identityElement; | |
| 125 | 121 | comptime var i: u8 = 0; |
| 126 | 122 | inline while (i < 16) : (i += 1) { |
| 127 | t.cMov(pc[i], ((@as(usize, (b ^ i)) -% 1) >> 8) & 1); | |
| 123 | t.cMov(pc[i], ((@as(usize, b ^ i) -% 1) >> 8) & 1); | |
| 128 | 124 | } |
| 129 | 125 | return t; |
| 130 | 126 | } |
| 131 | 127 | |
| 132 | 128 | fn pcMul(pc: [16]Edwards25519, s: [32]u8) !Edwards25519 { |
| 133 | var q = Edwards25519.identityElement(); | |
| 129 | var q = Edwards25519.identityElement; | |
| 134 | 130 | var pos: usize = 252; |
| 135 | 131 | while (true) : (pos -= 4) { |
| 136 | 132 | q = q.dbl().dbl().dbl().dbl(); |
| ... | ... | @@ -144,7 +140,7 @@ pub const Edwards25519 = struct { |
| 144 | 140 | |
| 145 | 141 | fn precompute(p: Edwards25519) [16]Edwards25519 { |
| 146 | 142 | var pc: [16]Edwards25519 = undefined; |
| 147 | pc[0] = Edwards25519.identityElement(); | |
| 143 | pc[0] = Edwards25519.identityElement; | |
| 148 | 144 | pc[1] = p; |
| 149 | 145 | var i: usize = 2; |
| 150 | 146 | while (i < 16) : (i += 1) { |
| ... | ... | @@ -153,11 +149,14 @@ pub const Edwards25519 = struct { |
| 153 | 149 | return pc; |
| 154 | 150 | } |
| 155 | 151 | |
| 156 | fn _mul(p: Edwards25519, s: [32]u8) !Edwards25519 { | |
| 152 | /// Multiply an Edwards25519 point by a scalar without clamping it. | |
| 153 | /// Return error.WeakPublicKey if the resulting point is | |
| 154 | /// the identity element. | |
| 155 | pub fn mul(p: Edwards25519, s: [32]u8) !Edwards25519 { | |
| 157 | 156 | var pc: [16]Edwards25519 = undefined; |
| 158 | 157 | if (p.is_base) { |
| 159 | 158 | @setEvalBranchQuota(10000); |
| 160 | pc = comptime precompute(Edwards25519.basePoint()); | |
| 159 | pc = comptime precompute(Edwards25519.basePoint); | |
| 161 | 160 | } else { |
| 162 | 161 | pc = precompute(p); |
| 163 | 162 | pc[4].rejectIdentity() catch |_| return error.WeakPublicKey; |
| ... | ... | @@ -174,20 +173,13 @@ pub const Edwards25519 = struct { |
| 174 | 173 | pub fn clampedMul(p: Edwards25519, s: [32]u8) !Edwards25519 { |
| 175 | 174 | var t: [32]u8 = s; |
| 176 | 175 | scalar.clamp(&t); |
| 177 | return _mul(p, t); | |
| 178 | } | |
| 179 | ||
| 180 | /// Multiply an Edwards25519 point by a scalar without clamping it. | |
| 181 | /// Return error.WeakPublicKey if the resulting point is | |
| 182 | /// the identity element. | |
| 183 | pub fn mul(p: Edwards25519, s: [32]u8) !Edwards25519 { | |
| 184 | return _mul(p, s); | |
| 176 | return mul(p, t); | |
| 185 | 177 | } |
| 186 | 178 | }; |
| 187 | 179 | |
| 188 | 180 | test "edwards25519 packing/unpacking" { |
| 189 | 181 | const s = [_]u8{170} ++ [_]u8{0} ** 31; |
| 190 | var b = Edwards25519.basePoint(); | |
| 182 | var b = Edwards25519.basePoint; | |
| 191 | 183 | const pk = try b.mul(s); |
| 192 | 184 | var buf: [128]u8 = undefined; |
| 193 | 185 | std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{pk.toBytes()}), "074BC7E0FCBD587FDBC0969444245FADC562809C8F6E97E949AF62484B5B81A6"); |
lib/std/crypto/25519/ristretto255.zig+3-5| ... | ... | @@ -43,10 +43,8 @@ pub const Ristretto255 = struct { |
| 43 | 43 | return p.p.rejectIdentity(); |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | /// Return the base point (Ristretto is a curve in desguise). | |
| 47 | pub inline fn basePoint() Ristretto255 { | |
| 48 | return .{ .p = Curve.basePoint() }; | |
| 49 | } | |
| 46 | /// The base point (Ristretto is a curve in desguise). | |
| 47 | pub const basePoint = Ristretto255{ .p = Curve.basePoint }; | |
| 50 | 48 | |
| 51 | 49 | /// Decode a Ristretto255 representative. |
| 52 | 50 | pub fn fromBytes(s: [32]u8) !Ristretto255 { |
| ... | ... | @@ -130,7 +128,7 @@ pub const Ristretto255 = struct { |
| 130 | 128 | }; |
| 131 | 129 | |
| 132 | 130 | test "ristretto255" { |
| 133 | const p = Ristretto255.basePoint(); | |
| 131 | const p = Ristretto255.basePoint; | |
| 134 | 132 | var buf: [256]u8 = undefined; |
| 135 | 133 | std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{p.toBytes()}), "E2F2AE0A6ABC4E71A884A961C500515F58E30B6AA582DD8DB6A65945E08D2D76"); |
| 136 | 134 |
lib/std/crypto/25519/x25519.zig+13-13| ... | ... | @@ -17,7 +17,7 @@ pub const X25519 = struct { |
| 17 | 17 | std.debug.assert(public_key.len >= minimum_key_length); |
| 18 | 18 | var s: [32]u8 = undefined; |
| 19 | 19 | mem.copy(u8, &s, private_key[0..32]); |
| 20 | if (Curve.basePoint().clampedMul(s)) |q| { | |
| 20 | if (Curve.basePoint.clampedMul(s)) |q| { | |
| 21 | 21 | mem.copy(u8, public_key, q.toBytes()[0..]); |
| 22 | 22 | return true; |
| 23 | 23 | } else |_| { |
| ... | ... | @@ -52,7 +52,7 @@ test "x25519 public key calculation from secret key" { |
| 52 | 52 | try fmt.hexToBytes(sk[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166"); |
| 53 | 53 | try fmt.hexToBytes(pk_expected[0..], "f1814f0e8ff1043d8a44d25babff3cedcae6c22c3edaa48f857ae70de2baae50"); |
| 54 | 54 | std.testing.expect(X25519.createPublicKey(pk_calculated[0..], &sk)); |
| 55 | std.testing.expect(std.mem.eql(u8, &pk_calculated, &pk_expected)); | |
| 55 | std.testing.expectEqual(pk_calculated, pk_expected); | |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | 58 | test "x25519 rfc7748 vector1" { |
| ... | ... | @@ -64,7 +64,7 @@ test "x25519 rfc7748 vector1" { |
| 64 | 64 | var output: [32]u8 = undefined; |
| 65 | 65 | |
| 66 | 66 | std.testing.expect(X25519.create(output[0..], secret_key[0..], public_key[0..])); |
| 67 | std.testing.expect(std.mem.eql(u8, &output, expected_output[0..])); | |
| 67 | std.testing.expectEqual(output, expected_output); | |
| 68 | 68 | } |
| 69 | 69 | |
| 70 | 70 | test "x25519 rfc7748 vector2" { |
| ... | ... | @@ -76,7 +76,7 @@ test "x25519 rfc7748 vector2" { |
| 76 | 76 | var output: [32]u8 = undefined; |
| 77 | 77 | |
| 78 | 78 | std.testing.expect(X25519.create(output[0..], secret_key[0..], public_key[0..])); |
| 79 | std.testing.expect(std.mem.eql(u8, &output, expected_output[0..])); | |
| 79 | std.testing.expectEqual(output, expected_output); | |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | 82 | test "x25519 rfc7748 one iteration" { |
| ... | ... | @@ -91,11 +91,11 @@ test "x25519 rfc7748 one iteration" { |
| 91 | 91 | var output: [32]u8 = undefined; |
| 92 | 92 | std.testing.expect(X25519.create(output[0..], &k, &u)); |
| 93 | 93 | |
| 94 | std.mem.copy(u8, u[0..], k[0..]); | |
| 95 | std.mem.copy(u8, k[0..], output[0..]); | |
| 94 | mem.copy(u8, u[0..], k[0..]); | |
| 95 | mem.copy(u8, k[0..], output[0..]); | |
| 96 | 96 | } |
| 97 | 97 | |
| 98 | std.testing.expect(std.mem.eql(u8, k[0..], expected_output[0..])); | |
| 98 | std.testing.expectEqual(k, expected_output); | |
| 99 | 99 | } |
| 100 | 100 | |
| 101 | 101 | test "x25519 rfc7748 1,000 iterations" { |
| ... | ... | @@ -115,11 +115,11 @@ test "x25519 rfc7748 1,000 iterations" { |
| 115 | 115 | var output: [32]u8 = undefined; |
| 116 | 116 | std.testing.expect(X25519.create(output[0..], &k, &u)); |
| 117 | 117 | |
| 118 | std.mem.copy(u8, u[0..], k[0..]); | |
| 119 | std.mem.copy(u8, k[0..], output[0..]); | |
| 118 | mem.copy(u8, u[0..], k[0..]); | |
| 119 | mem.copy(u8, k[0..], output[0..]); | |
| 120 | 120 | } |
| 121 | 121 | |
| 122 | std.testing.expect(std.mem.eql(u8, k[0..], expected_output)); | |
| 122 | std.testing.expectEqual(k, expected_output); | |
| 123 | 123 | } |
| 124 | 124 | |
| 125 | 125 | test "x25519 rfc7748 1,000,000 iterations" { |
| ... | ... | @@ -138,9 +138,9 @@ test "x25519 rfc7748 1,000,000 iterations" { |
| 138 | 138 | var output: [32]u8 = undefined; |
| 139 | 139 | std.testing.expect(X25519.create(output[0..], &k, &u)); |
| 140 | 140 | |
| 141 | std.mem.copy(u8, u[0..], k[0..]); | |
| 142 | std.mem.copy(u8, k[0..], output[0..]); | |
| 141 | mem.copy(u8, u[0..], k[0..]); | |
| 142 | mem.copy(u8, k[0..], output[0..]); | |
| 143 | 143 | } |
| 144 | 144 | |
| 145 | std.testing.expect(std.mem.eql(u8, k[0..], expected_output)); | |
| 145 | std.testing.expectEqual(k[0..], expected_output); | |
| 146 | 146 | } |