authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2020-08-15 10:15:42+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-16 22:35:27-07:00
logbcef123d902b9d1d8a27b0414932b1b92f6f1a7e
tree22ad97205c0a529cc5d832ba21ec709d11442843
parent263c44473896597346bc244d82a2b436d7d2da02

Address more review issues


5 files changed, 49 insertions(+), 54 deletions(-)

lib/std/crypto/25519/curve25519.zig+3-5
...@@ -19,10 +19,8 @@ pub const Curve25519 = struct {...@@ -19,10 +19,8 @@ pub const Curve25519 = struct {
19 return p.x.toBytes();19 return p.x.toBytes();
20 }20 }
2121
22 /// Return the Curve25519 base point.22 /// The Curve25519 base point.
23 pub inline fn basePoint() Curve25519 {23 pub const basePoint = Curve25519{ .x = Fe.curve25519BasePoint };
24 return .{ .x = Fe.curve25519BasePoint };
25 }
2624
27 /// Check that the encoding of a Curve25519 point is canonical.25 /// Check that the encoding of a Curve25519 point is canonical.
28 pub fn rejectNonCanonical(s: [32]u8) !void {26 pub fn rejectNonCanonical(s: [32]u8) !void {
...@@ -103,7 +101,7 @@ pub const Curve25519 = struct {...@@ -103,7 +101,7 @@ pub const Curve25519 = struct {
103101
104test "curve25519" {102test "curve25519" {
105 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 };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 try p.rejectIdentity();105 try p.rejectIdentity();
108 var buf: [128]u8 = undefined;106 var buf: [128]u8 = undefined;
109 std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{p.toBytes()}), "E6F2A4D1C28EE5C7AD0329268255A468AD407D2672824C0C0EB30EA6EF450145");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,12 +19,19 @@ pub const Ed25519 = struct {
19 pub const noise_length = 32;19 pub const noise_length = 32;
2020
21 /// Derive a key pair from a secret seed.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 pub fn createKeyPair(seed: [seed_length]u8) ![keypair_length]u8 {29 pub fn createKeyPair(seed: [seed_length]u8) ![keypair_length]u8 {
23 var az: [Sha512.digest_length]u8 = undefined;30 var az: [Sha512.digest_length]u8 = undefined;
24 var h = Sha512.init();31 var h = Sha512.init();
25 h.update(&seed);32 h.update(&seed);
26 h.final(&az);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 var keypair: [keypair_length]u8 = undefined;35 var keypair: [keypair_length]u8 = undefined;
29 mem.copy(u8, &keypair, &seed);36 mem.copy(u8, &keypair, &seed);
30 mem.copy(u8, keypair[seed_length..], &p.toBytes());37 mem.copy(u8, keypair[seed_length..], &p.toBytes());
...@@ -57,7 +64,7 @@ pub const Ed25519 = struct {...@@ -57,7 +64,7 @@ pub const Ed25519 = struct {
57 var nonce64: [64]u8 = undefined;64 var nonce64: [64]u8 = undefined;
58 h.final(&nonce64);65 h.final(&nonce64);
59 const nonce = Curve.scalar.reduce64(nonce64);66 const nonce = Curve.scalar.reduce64(nonce64);
60 const r = try Curve.basePoint().mul(nonce);67 const r = try Curve.basePoint.mul(nonce);
6168
62 var sig: [signature_length]u8 = undefined;69 var sig: [signature_length]u8 = undefined;
63 mem.copy(u8, sig[0..32], &r.toBytes());70 mem.copy(u8, sig[0..32], &r.toBytes());
...@@ -95,7 +102,7 @@ pub const Ed25519 = struct {...@@ -95,7 +102,7 @@ pub const Ed25519 = struct {
95 const hram = Curve.scalar.reduce64(hram64);102 const hram = Curve.scalar.reduce64(hram64);
96103
97 const p = try a.neg().mul(hram);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 if (mem.eql(u8, &check, r) == false) {106 if (mem.eql(u8, &check, r) == false) {
100 return error.InvalidSignature;107 return error.InvalidSignature;
101 }108 }
lib/std/crypto/25519/edwards25519.zig+20-28
...@@ -50,20 +50,16 @@ pub const Edwards25519 = struct {...@@ -50,20 +50,16 @@ pub const Edwards25519 = struct {
50 return Fe.rejectNonCanonical(s, true);50 return Fe.rejectNonCanonical(s, true);
51 }51 }
5252
53 /// Return the Edwards25519 base point.53 /// The edwards25519 base point.
54 pub inline fn basePoint() Edwards25519 {54 pub const basePoint = Edwards25519{
55 return .{55 .x = Fe{ .limbs = .{ 3990542415680775, 3398198340507945, 4322667446711068, 2814063955482877, 2839572215813860 } },
56 .x = Fe{ .limbs = .{ 3990542415680775, 3398198340507945, 4322667446711068, 2814063955482877, 2839572215813860 } },56 .y = Fe{ .limbs = .{ 1801439850948184, 1351079888211148, 450359962737049, 900719925474099, 1801439850948198 } },
57 .y = Fe{ .limbs = .{ 1801439850948184, 1351079888211148, 450359962737049, 900719925474099, 1801439850948198 } },57 .z = Fe.one,
58 .z = Fe.one,58 .t = Fe{ .limbs = .{ 1841354044333475, 16398895984059, 755974180946558, 900171276175154, 1821297809914039 } },
59 .t = Fe{ .limbs = .{ 1841354044333475, 16398895984059, 755974180946558, 900171276175154, 1821297809914039 } },59 .is_base = true,
60 .is_base = true,60 };
61 };
62 }
6361
64 inline fn identityElement() Edwards25519 {62 const identityElement = Edwards25519{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero };
65 return .{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero };
66 }
6763
68 /// Reject the neutral element.64 /// Reject the neutral element.
69 pub fn rejectIdentity(p: Edwards25519) !void {65 pub fn rejectIdentity(p: Edwards25519) !void {
...@@ -121,16 +117,16 @@ pub const Edwards25519 = struct {...@@ -121,16 +117,16 @@ pub const Edwards25519 = struct {
121 }117 }
122118
123 inline fn pcSelect(pc: [16]Edwards25519, b: u8) Edwards25519 {119 inline fn pcSelect(pc: [16]Edwards25519, b: u8) Edwards25519 {
124 var t = Edwards25519.identityElement();120 var t = Edwards25519.identityElement;
125 comptime var i: u8 = 0;121 comptime var i: u8 = 0;
126 inline while (i < 16) : (i += 1) {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 return t;125 return t;
130 }126 }
131127
132 fn pcMul(pc: [16]Edwards25519, s: [32]u8) !Edwards25519 {128 fn pcMul(pc: [16]Edwards25519, s: [32]u8) !Edwards25519 {
133 var q = Edwards25519.identityElement();129 var q = Edwards25519.identityElement;
134 var pos: usize = 252;130 var pos: usize = 252;
135 while (true) : (pos -= 4) {131 while (true) : (pos -= 4) {
136 q = q.dbl().dbl().dbl().dbl();132 q = q.dbl().dbl().dbl().dbl();
...@@ -144,7 +140,7 @@ pub const Edwards25519 = struct {...@@ -144,7 +140,7 @@ pub const Edwards25519 = struct {
144140
145 fn precompute(p: Edwards25519) [16]Edwards25519 {141 fn precompute(p: Edwards25519) [16]Edwards25519 {
146 var pc: [16]Edwards25519 = undefined;142 var pc: [16]Edwards25519 = undefined;
147 pc[0] = Edwards25519.identityElement();143 pc[0] = Edwards25519.identityElement;
148 pc[1] = p;144 pc[1] = p;
149 var i: usize = 2;145 var i: usize = 2;
150 while (i < 16) : (i += 1) {146 while (i < 16) : (i += 1) {
...@@ -153,11 +149,14 @@ pub const Edwards25519 = struct {...@@ -153,11 +149,14 @@ pub const Edwards25519 = struct {
153 return pc;149 return pc;
154 }150 }
155151
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 var pc: [16]Edwards25519 = undefined;156 var pc: [16]Edwards25519 = undefined;
158 if (p.is_base) {157 if (p.is_base) {
159 @setEvalBranchQuota(10000);158 @setEvalBranchQuota(10000);
160 pc = comptime precompute(Edwards25519.basePoint());159 pc = comptime precompute(Edwards25519.basePoint);
161 } else {160 } else {
162 pc = precompute(p);161 pc = precompute(p);
163 pc[4].rejectIdentity() catch |_| return error.WeakPublicKey;162 pc[4].rejectIdentity() catch |_| return error.WeakPublicKey;
...@@ -174,20 +173,13 @@ pub const Edwards25519 = struct {...@@ -174,20 +173,13 @@ pub const Edwards25519 = struct {
174 pub fn clampedMul(p: Edwards25519, s: [32]u8) !Edwards25519 {173 pub fn clampedMul(p: Edwards25519, s: [32]u8) !Edwards25519 {
175 var t: [32]u8 = s;174 var t: [32]u8 = s;
176 scalar.clamp(&t);175 scalar.clamp(&t);
177 return _mul(p, t);176 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);
185 }177 }
186};178};
187179
188test "edwards25519 packing/unpacking" {180test "edwards25519 packing/unpacking" {
189 const s = [_]u8{170} ++ [_]u8{0} ** 31;181 const s = [_]u8{170} ++ [_]u8{0} ** 31;
190 var b = Edwards25519.basePoint();182 var b = Edwards25519.basePoint;
191 const pk = try b.mul(s);183 const pk = try b.mul(s);
192 var buf: [128]u8 = undefined;184 var buf: [128]u8 = undefined;
193 std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{pk.toBytes()}), "074BC7E0FCBD587FDBC0969444245FADC562809C8F6E97E949AF62484B5B81A6");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,10 +43,8 @@ pub const Ristretto255 = struct {
43 return p.p.rejectIdentity();43 return p.p.rejectIdentity();
44 }44 }
4545
46 /// Return the base point (Ristretto is a curve in desguise).46 /// The base point (Ristretto is a curve in desguise).
47 pub inline fn basePoint() Ristretto255 {47 pub const basePoint = Ristretto255{ .p = Curve.basePoint };
48 return .{ .p = Curve.basePoint() };
49 }
5048
51 /// Decode a Ristretto255 representative.49 /// Decode a Ristretto255 representative.
52 pub fn fromBytes(s: [32]u8) !Ristretto255 {50 pub fn fromBytes(s: [32]u8) !Ristretto255 {
...@@ -130,7 +128,7 @@ pub const Ristretto255 = struct {...@@ -130,7 +128,7 @@ pub const Ristretto255 = struct {
130};128};
131129
132test "ristretto255" {130test "ristretto255" {
133 const p = Ristretto255.basePoint();131 const p = Ristretto255.basePoint;
134 var buf: [256]u8 = undefined;132 var buf: [256]u8 = undefined;
135 std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{p.toBytes()}), "E2F2AE0A6ABC4E71A884A961C500515F58E30B6AA582DD8DB6A65945E08D2D76");133 std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{p.toBytes()}), "E2F2AE0A6ABC4E71A884A961C500515F58E30B6AA582DD8DB6A65945E08D2D76");
136134
lib/std/crypto/25519/x25519.zig+13-13
...@@ -17,7 +17,7 @@ pub const X25519 = struct {...@@ -17,7 +17,7 @@ pub const X25519 = struct {
17 std.debug.assert(public_key.len >= minimum_key_length);17 std.debug.assert(public_key.len >= minimum_key_length);
18 var s: [32]u8 = undefined;18 var s: [32]u8 = undefined;
19 mem.copy(u8, &s, private_key[0..32]);19 mem.copy(u8, &s, private_key[0..32]);
20 if (Curve.basePoint().clampedMul(s)) |q| {20 if (Curve.basePoint.clampedMul(s)) |q| {
21 mem.copy(u8, public_key, q.toBytes()[0..]);21 mem.copy(u8, public_key, q.toBytes()[0..]);
22 return true;22 return true;
23 } else |_| {23 } else |_| {
...@@ -52,7 +52,7 @@ test "x25519 public key calculation from secret key" {...@@ -52,7 +52,7 @@ test "x25519 public key calculation from secret key" {
52 try fmt.hexToBytes(sk[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");52 try fmt.hexToBytes(sk[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");
53 try fmt.hexToBytes(pk_expected[0..], "f1814f0e8ff1043d8a44d25babff3cedcae6c22c3edaa48f857ae70de2baae50");53 try fmt.hexToBytes(pk_expected[0..], "f1814f0e8ff1043d8a44d25babff3cedcae6c22c3edaa48f857ae70de2baae50");
54 std.testing.expect(X25519.createPublicKey(pk_calculated[0..], &sk));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}
5757
58test "x25519 rfc7748 vector1" {58test "x25519 rfc7748 vector1" {
...@@ -64,7 +64,7 @@ test "x25519 rfc7748 vector1" {...@@ -64,7 +64,7 @@ test "x25519 rfc7748 vector1" {
64 var output: [32]u8 = undefined;64 var output: [32]u8 = undefined;
6565
66 std.testing.expect(X25519.create(output[0..], secret_key[0..], public_key[0..]));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}
6969
70test "x25519 rfc7748 vector2" {70test "x25519 rfc7748 vector2" {
...@@ -76,7 +76,7 @@ test "x25519 rfc7748 vector2" {...@@ -76,7 +76,7 @@ test "x25519 rfc7748 vector2" {
76 var output: [32]u8 = undefined;76 var output: [32]u8 = undefined;
7777
78 std.testing.expect(X25519.create(output[0..], secret_key[0..], public_key[0..]));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}
8181
82test "x25519 rfc7748 one iteration" {82test "x25519 rfc7748 one iteration" {
...@@ -91,11 +91,11 @@ test "x25519 rfc7748 one iteration" {...@@ -91,11 +91,11 @@ test "x25519 rfc7748 one iteration" {
91 var output: [32]u8 = undefined;91 var output: [32]u8 = undefined;
92 std.testing.expect(X25519.create(output[0..], &k, &u));92 std.testing.expect(X25519.create(output[0..], &k, &u));
9393
94 std.mem.copy(u8, u[0..], k[0..]);94 mem.copy(u8, u[0..], k[0..]);
95 std.mem.copy(u8, k[0..], output[0..]);95 mem.copy(u8, k[0..], output[0..]);
96 }96 }
9797
98 std.testing.expect(std.mem.eql(u8, k[0..], expected_output[0..]));98 std.testing.expectEqual(k, expected_output);
99}99}
100100
101test "x25519 rfc7748 1,000 iterations" {101test "x25519 rfc7748 1,000 iterations" {
...@@ -115,11 +115,11 @@ test "x25519 rfc7748 1,000 iterations" {...@@ -115,11 +115,11 @@ test "x25519 rfc7748 1,000 iterations" {
115 var output: [32]u8 = undefined;115 var output: [32]u8 = undefined;
116 std.testing.expect(X25519.create(output[0..], &k, &u));116 std.testing.expect(X25519.create(output[0..], &k, &u));
117117
118 std.mem.copy(u8, u[0..], k[0..]);118 mem.copy(u8, u[0..], k[0..]);
119 std.mem.copy(u8, k[0..], output[0..]);119 mem.copy(u8, k[0..], output[0..]);
120 }120 }
121121
122 std.testing.expect(std.mem.eql(u8, k[0..], expected_output));122 std.testing.expectEqual(k, expected_output);
123}123}
124124
125test "x25519 rfc7748 1,000,000 iterations" {125test "x25519 rfc7748 1,000,000 iterations" {
...@@ -138,9 +138,9 @@ test "x25519 rfc7748 1,000,000 iterations" {...@@ -138,9 +138,9 @@ test "x25519 rfc7748 1,000,000 iterations" {
138 var output: [32]u8 = undefined;138 var output: [32]u8 = undefined;
139 std.testing.expect(X25519.create(output[0..], &k, &u));139 std.testing.expect(X25519.create(output[0..], &k, &u));
140140
141 std.mem.copy(u8, u[0..], k[0..]);141 mem.copy(u8, u[0..], k[0..]);
142 std.mem.copy(u8, k[0..], output[0..]);142 mem.copy(u8, k[0..], output[0..]);
143 }143 }
144144
145 std.testing.expect(std.mem.eql(u8, k[0..], expected_output));145 std.testing.expectEqual(k[0..], expected_output);
146}146}