authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2020-08-15 08:38:44+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-16 22:35:27-07:00
loged558bfbaa737b187d894eddb8573cde15a3fb33
treeea741ebad482cb9bfb1d5a13413d62bbc82fd428
parentdd8f7b396c24d78168d9582364ab5b3b4606ccc5

Address @daurnimator feedback


7 files changed, 79 insertions(+), 106 deletions(-)

lib/std/crypto/25519/curve25519.zig+9-10
...@@ -21,7 +21,7 @@ pub const Curve25519 = struct {...@@ -21,7 +21,7 @@ pub const Curve25519 = struct {
2121
22 /// Return the Curve25519 base point.22 /// Return the Curve25519 base point.
23 pub inline fn basePoint() Curve25519 {23 pub inline fn basePoint() Curve25519 {
24 return .{ .x = Fe.curve25519BasePoint() };24 return .{ .x = Fe.curve25519BasePoint };
25 }25 }
2626
27 /// Check that the encoding of a Curve25519 point is canonical.27 /// Check that the encoding of a Curve25519 point is canonical.
...@@ -38,10 +38,10 @@ pub const Curve25519 = struct {...@@ -38,10 +38,10 @@ pub const Curve25519 = struct {
3838
39 fn ladder(p: Curve25519, s: [32]u8, comptime bits: usize) !Curve25519 {39 fn ladder(p: Curve25519, s: [32]u8, comptime bits: usize) !Curve25519 {
40 var x1 = p.x;40 var x1 = p.x;
41 var x2 = Fe.one();41 var x2 = Fe.one;
42 var z2 = Fe.zero();42 var z2 = Fe.zero;
43 var x3 = x1;43 var x3 = x1;
44 var z3 = Fe.one();44 var z3 = Fe.one;
45 var swap: u8 = 0;45 var swap: u8 = 0;
46 var pos: usize = bits - 1;46 var pos: usize = bits - 1;
47 while (true) {47 while (true) {
...@@ -76,7 +76,7 @@ pub const Curve25519 = struct {...@@ -76,7 +76,7 @@ pub const Curve25519 = struct {
76 if (x2.isZero()) {76 if (x2.isZero()) {
77 return error.IdentityElement;77 return error.IdentityElement;
78 }78 }
79 return Curve25519 { .x = x2 };79 return Curve25519{ .x = x2 };
80 }80 }
8181
82 /// Multiply a Curve25519 point by a scalar after "clamping" it.82 /// Multiply a Curve25519 point by a scalar after "clamping" it.
...@@ -88,7 +88,7 @@ pub const Curve25519 = struct {...@@ -88,7 +88,7 @@ pub const Curve25519 = struct {
88 pub fn clampedMul(p: Curve25519, s: [32]u8) !Curve25519 {88 pub fn clampedMul(p: Curve25519, s: [32]u8) !Curve25519 {
89 var t: [32]u8 = s;89 var t: [32]u8 = s;
90 scalar.clamp(&t);90 scalar.clamp(&t);
91 return ladder(p, t, 255);91 return try ladder(p, t, 255);
92 }92 }
9393
94 /// Multiply a Curve25519 point by a scalar without clamping it.94 /// Multiply a Curve25519 point by a scalar without clamping it.
...@@ -98,7 +98,7 @@ pub const Curve25519 = struct {...@@ -98,7 +98,7 @@ pub const Curve25519 = struct {
98 pub fn mul(p: Curve25519, s: [32]u8) !Curve25519 {98 pub fn mul(p: Curve25519, s: [32]u8) !Curve25519 {
99 const cofactor = [_]u8{8} ++ [_]u8{0} ** 31;99 const cofactor = [_]u8{8} ++ [_]u8{0} ** 31;
100 _ = ladder(p, cofactor, 4) catch |_| return error.WeakPublicKey;100 _ = ladder(p, cofactor, 4) catch |_| return error.WeakPublicKey;
101 return ladder(p, s, 256);101 return try ladder(p, s, 256);
102 }102 }
103};103};
104104
...@@ -107,10 +107,9 @@ test "curve25519" {...@@ -107,10 +107,9 @@ test "curve25519" {
107 const p = try Curve25519.basePoint().clampedMul(s);107 const p = try Curve25519.basePoint().clampedMul(s);
108 try p.rejectIdentity();108 try p.rejectIdentity();
109 var buf: [128]u8 = undefined;109 var buf: [128]u8 = undefined;
110 const alloc = &std.heap.FixedBufferAllocator.init(&buf).allocator;110 std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{p.toBytes()}), "E6F2A4D1C28EE5C7AD0329268255A468AD407D2672824C0C0EB30EA6EF450145");
111 std.testing.expectEqualStrings(try std.fmt.allocPrint(alloc, "{X}", .{p.toBytes()}), "E6F2A4D1C28EE5C7AD0329268255A468AD407D2672824C0C0EB30EA6EF450145");
112 const q = try p.clampedMul(s);111 const q = try p.clampedMul(s);
113 std.testing.expectEqualStrings(try std.fmt.allocPrint(alloc, "{X}", .{q.toBytes()}), "3614E119FFE55EC55B87D6B19971A9F4CBC78EFE80BEC55B96392BABCC712537");112 std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{q.toBytes()}), "3614E119FFE55EC55B87D6B19971A9F4CBC78EFE80BEC55B96392BABCC712537");
114113
115 try Curve25519.rejectNonCanonical(s);114 try Curve25519.rejectNonCanonical(s);
116 s[31] |= 0x80;115 s[31] |= 0x80;
lib/std/crypto/25519/ed25519.zig+3-5
...@@ -107,11 +107,10 @@ test "ed25519 key pair creation" {...@@ -107,11 +107,10 @@ test "ed25519 key pair creation" {
107 try fmt.hexToBytes(seed[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");107 try fmt.hexToBytes(seed[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");
108 const key_pair = try Ed25519.createKeyPair(seed);108 const key_pair = try Ed25519.createKeyPair(seed);
109 var buf: [256]u8 = undefined;109 var buf: [256]u8 = undefined;
110 const alloc = &std.heap.FixedBufferAllocator.init(&buf).allocator;110 std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{key_pair}), "8052030376D47112BE7F73ED7A019293DD12AD910B654455798B4667D73DE1662D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083");
111 std.testing.expectEqualStrings(try std.fmt.allocPrint(alloc, "{X}", .{key_pair}), "8052030376D47112BE7F73ED7A019293DD12AD910B654455798B4667D73DE1662D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083");
112111
113 const public_key = Ed25519.publicKey(key_pair);112 const public_key = Ed25519.publicKey(key_pair);
114 std.testing.expectEqualStrings(try std.fmt.allocPrint(alloc, "{X}", .{public_key}), "2D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083");113 std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{public_key}), "2D6F7455D97B4A3A10D7293909D1A4F2058CB9A370E43FA8154BB280DB839083");
115}114}
116115
117test "ed25519 signature" {116test "ed25519 signature" {
...@@ -121,8 +120,7 @@ test "ed25519 signature" {...@@ -121,8 +120,7 @@ test "ed25519 signature" {
121120
122 const sig = try Ed25519.sign("test", key_pair, null);121 const sig = try Ed25519.sign("test", key_pair, null);
123 var buf: [128]u8 = undefined;122 var buf: [128]u8 = undefined;
124 const alloc = &std.heap.FixedBufferAllocator.init(&buf).allocator;123 std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{sig}), "10A442B4A80CC4225B154F43BEF28D2472CA80221951262EB8E0DF9091575E2687CC486E77263C3418C757522D54F84B0359236ABBBD4ACD20DC297FDCA66808");
125 std.testing.expectEqualStrings(try std.fmt.allocPrint(alloc, "{X}", .{sig}), "10A442B4A80CC4225B154F43BEF28D2472CA80221951262EB8E0DF9091575E2687CC486E77263C3418C757522D54F84B0359236ABBBD4ACD20DC297FDCA66808");
126 const public_key = Ed25519.publicKey(key_pair);124 const public_key = Ed25519.publicKey(key_pair);
127 try Ed25519.verify(sig, "test", public_key);125 try Ed25519.verify(sig, "test", public_key);
128 std.testing.expectError(error.InvalidSignature, Ed25519.verify(sig, "TEST", public_key));126 std.testing.expectError(error.InvalidSignature, Ed25519.verify(sig, "TEST", public_key));
lib/std/crypto/25519/edwards25519.zig+9-10
...@@ -17,10 +17,10 @@ pub const Edwards25519 = struct {...@@ -17,10 +17,10 @@ pub const Edwards25519 = struct {
1717
18 /// Decode an Edwards25519 point from its compressed (Y+sign) coordinates.18 /// Decode an Edwards25519 point from its compressed (Y+sign) coordinates.
19 pub fn fromBytes(s: [32]u8) !Edwards25519 {19 pub fn fromBytes(s: [32]u8) !Edwards25519 {
20 const z = Fe.one();20 const z = Fe.one;
21 const y = Fe.fromBytes(s);21 const y = Fe.fromBytes(s);
22 var u = y.sq();22 var u = y.sq();
23 var v = u.mul(Fe.edwards25519d());23 var v = u.mul(Fe.edwards25519d);
24 u = u.sub(z);24 u = u.sub(z);
25 v = v.add(z);25 v = v.add(z);
26 const v3 = v.sq().mul(v);26 const v3 = v.sq().mul(v);
...@@ -31,10 +31,10 @@ pub const Edwards25519 = struct {...@@ -31,10 +31,10 @@ pub const Edwards25519 = struct {
31 if ((@boolToInt(has_m_root) | @boolToInt(has_p_root)) == 0) {31 if ((@boolToInt(has_m_root) | @boolToInt(has_p_root)) == 0) {
32 return error.InvalidEncoding;32 return error.InvalidEncoding;
33 }33 }
34 x.cMov(x.mul(Fe.sqrtm1()), 1 - @boolToInt(has_m_root));34 x.cMov(x.mul(Fe.sqrtm1), 1 - @boolToInt(has_m_root));
35 x.cMov(x.neg(), @boolToInt(x.isNegative()) ^ (s[31] >> 7));35 x.cMov(x.neg(), @boolToInt(x.isNegative()) ^ (s[31] >> 7));
36 const t = x.mul(y);36 const t = x.mul(y);
37 return Edwards25519 { .x = x, .y = y, .z = z, .t = t };37 return Edwards25519{ .x = x, .y = y, .z = z, .t = t };
38 }38 }
3939
40 /// Encode an Edwards25519 point.40 /// Encode an Edwards25519 point.
...@@ -55,14 +55,14 @@ pub const Edwards25519 = struct {...@@ -55,14 +55,14 @@ pub const Edwards25519 = struct {
55 return .{55 return .{
56 .x = Fe{ .limbs = .{ 3990542415680775, 3398198340507945, 4322667446711068, 2814063955482877, 2839572215813860 } },56 .x = Fe{ .limbs = .{ 3990542415680775, 3398198340507945, 4322667446711068, 2814063955482877, 2839572215813860 } },
57 .y = Fe{ .limbs = .{ 1801439850948184, 1351079888211148, 450359962737049, 900719925474099, 1801439850948198 } },57 .y = Fe{ .limbs = .{ 1801439850948184, 1351079888211148, 450359962737049, 900719925474099, 1801439850948198 } },
58 .z = Fe.one(),58 .z = Fe.one,
59 .t = Fe{ .limbs = .{ 1841354044333475, 16398895984059, 755974180946558, 900171276175154, 1821297809914039 } },59 .t = Fe{ .limbs = .{ 1841354044333475, 16398895984059, 755974180946558, 900171276175154, 1821297809914039 } },
60 .is_base = true,60 .is_base = true,
61 };61 };
62 }62 }
6363
64 inline fn identityElement() Edwards25519 {64 inline fn identityElement() Edwards25519 {
65 return .{ .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 }66 }
6767
68 /// Reject the neutral element.68 /// Reject the neutral element.
...@@ -98,7 +98,7 @@ pub const Edwards25519 = struct {...@@ -98,7 +98,7 @@ pub const Edwards25519 = struct {
98 pub inline fn add(p: Edwards25519, q: Edwards25519) Edwards25519 {98 pub inline fn add(p: Edwards25519, q: Edwards25519) Edwards25519 {
99 const a = p.y.sub(p.x).mul(q.y.sub(q.x));99 const a = p.y.sub(p.x).mul(q.y.sub(q.x));
100 const b = p.x.add(p.y).mul(q.x.add(q.y));100 const b = p.x.add(p.y).mul(q.x.add(q.y));
101 const c = p.t.mul(q.t).mul(Fe.edwards25519d2());101 const c = p.t.mul(q.t).mul(Fe.edwards25519d2);
102 var d = p.z.mul(q.z);102 var d = p.z.mul(q.z);
103 d = d.add(d);103 d = d.add(d);
104 const x = b.sub(a);104 const x = b.sub(a);
...@@ -124,7 +124,7 @@ pub const Edwards25519 = struct {...@@ -124,7 +124,7 @@ pub const Edwards25519 = struct {
124 var t = Edwards25519.identityElement();124 var t = Edwards25519.identityElement();
125 comptime var i: u8 = 0;125 comptime var i: u8 = 0;
126 inline while (i < 16) : (i += 1) {126 inline while (i < 16) : (i += 1) {
127 t.cMov(pc[i], ((@intCast(usize, (b ^ i)) -% 1) >> 8) & 1);127 t.cMov(pc[i], ((@as(usize, (b ^ i)) -% 1) >> 8) & 1);
128 }128 }
129 return t;129 return t;
130 }130 }
...@@ -191,8 +191,7 @@ test "edwards25519 packing/unpacking" {...@@ -191,8 +191,7 @@ test "edwards25519 packing/unpacking" {
191 var b = Edwards25519.basePoint();191 var b = Edwards25519.basePoint();
192 const pk = try b.mul(s);192 const pk = try b.mul(s);
193 var buf: [128]u8 = undefined;193 var buf: [128]u8 = undefined;
194 const alloc = &std.heap.FixedBufferAllocator.init(&buf).allocator;194 std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{pk.toBytes()}), "074BC7E0FCBD587FDBC0969444245FADC562809C8F6E97E949AF62484B5B81A6");
195 std.testing.expectEqualStrings(try std.fmt.allocPrint(alloc, "{X}", .{pk.toBytes()}), "074BC7E0FCBD587FDBC0969444245FADC562809C8F6E97E949AF62484B5B81A6");
196195
197 const small_order_ss: [7][32]u8 = .{196 const small_order_ss: [7][32]u8 = .{
198 .{197 .{
lib/std/crypto/25519/field.zig+9-24
...@@ -7,34 +7,19 @@ pub const Fe = struct {...@@ -7,34 +7,19 @@ pub const Fe = struct {
77
8 const MASK51: u64 = 0x7ffffffffffff;8 const MASK51: u64 = 0x7ffffffffffff;
99
10 pub inline fn zero() Fe {10 pub const zero = Fe{ .limbs = .{ 0, 0, 0, 0, 0 } };
11 return .{ .limbs = .{ 0, 0, 0, 0, 0 } };
12 }
1311
14 pub inline fn one() Fe {12 pub const one = Fe{ .limbs = .{ 1, 0, 0, 0, 0 } };
15 return .{ .limbs = .{ 1, 0, 0, 0, 0 } };
16 }
1713
18 pub inline fn sqrtm1() Fe {14 pub const sqrtm1 = Fe{ .limbs = .{ 1718705420411056, 234908883556509, 2233514472574048, 2117202627021982, 765476049583133 } }; // sqrt(-1)
19 return .{ .limbs = .{ 1718705420411056, 234908883556509, 2233514472574048, 2117202627021982, 765476049583133 } }; // sqrt(-1)
20 }
2115
22 pub inline fn curve25519BasePoint() Fe {16 pub const curve25519BasePoint = Fe{ .limbs = .{ 9, 0, 0, 0, 0 } };
23 return .{ .limbs = .{ 9, 0, 0, 0, 0 } };
24 }
2517
26 pub inline fn edwards25519d() Fe {18 pub const edwards25519d = Fe{ .limbs = .{ 929955233495203, 466365720129213, 1662059464998953, 2033849074728123, 1442794654840575 } }; // 37095705934669439343138083508754565189542113879843219016388785533085940283555
27 return .{ .limbs = .{ 929955233495203, 466365720129213, 1662059464998953, 2033849074728123, 1442794654840575 } }; // 37095705934669439343138083508754565189542113879843219016388785533085940283555
28 }
2919
30 pub inline fn edwards25519d2() Fe {20 pub const edwards25519d2 = Fe{ .limbs = .{ 1859910466990425, 932731440258426, 1072319116312658, 1815898335770999, 633789495995903 } }; // 2d
31 return .{ .limbs = .{ 1859910466990425, 932731440258426, 1072319116312658, 1815898335770999, 633789495995903 } }; // 2d
32 }
3321
34 // 1/sqrt(a-d)22 pub const edwards25519sqrtamd = Fe{ .limbs = .{ 278908739862762, 821645201101625, 8113234426968, 1777959178193151, 2118520810568447 } }; // 1/sqrt(a-d)
35 pub inline fn edwards25519sqrtamd() Fe {
36 return .{ .limbs = .{ 278908739862762, 821645201101625, 8113234426968, 1777959178193151, 2118520810568447 } };
37 }
3823
39 pub inline fn isZero(fe: Fe) bool {24 pub inline fn isZero(fe: Fe) bool {
40 var reduced = fe;25 var reduced = fe;
...@@ -77,7 +62,7 @@ pub const Fe = struct {...@@ -77,7 +62,7 @@ pub const Fe = struct {
77 c |= s[i] ^ 0xff;62 c |= s[i] ^ 0xff;
78 }63 }
79 c = (c -% 1) >> 8;64 c = (c -% 1) >> 8;
80 const d = (@intCast(u16, 0xed - 1) -% @intCast(u16, s[0])) >> 8;65 const d = (@as(u16, 0xed - 1) -% @as(u16, s[0])) >> 8;
81 const x = if (ignore_extra_bit) 0 else s[31] >> 7;66 const x = if (ignore_extra_bit) 0 else s[31] >> 7;
82 if ((((c & d) | x) & 1) != 0) {67 if ((((c & d) | x) & 1) != 0) {
83 return error.NonCanonical;68 return error.NonCanonical;
...@@ -148,7 +133,7 @@ pub const Fe = struct {...@@ -148,7 +133,7 @@ pub const Fe = struct {
148 }133 }
149134
150 pub inline fn neg(a: Fe) Fe {135 pub inline fn neg(a: Fe) Fe {
151 return zero().sub(a);136 return zero.sub(a);
152 }137 }
153138
154 pub inline fn isNegative(a: Fe) bool {139 pub inline fn isNegative(a: Fe) bool {
lib/std/crypto/25519/ristretto255.zig+16-17
...@@ -18,11 +18,11 @@ pub const Ristretto255 = struct {...@@ -18,11 +18,11 @@ pub const Ristretto255 = struct {
18 const vxx = x.sq().mul(v); // vx^218 const vxx = x.sq().mul(v); // vx^2
19 const m_root_check = vxx.sub(u); // vx^2-u19 const m_root_check = vxx.sub(u); // vx^2-u
20 const p_root_check = vxx.add(u); // vx^2+u20 const p_root_check = vxx.add(u); // vx^2+u
21 const f_root_check = u.mul(Fe.sqrtm1()).add(vxx); // vx^2+u*sqrt(-1)21 const f_root_check = u.mul(Fe.sqrtm1).add(vxx); // vx^2+u*sqrt(-1)
22 const has_m_root = m_root_check.isZero();22 const has_m_root = m_root_check.isZero();
23 const has_p_root = p_root_check.isZero();23 const has_p_root = p_root_check.isZero();
24 const has_f_root = f_root_check.isZero();24 const has_f_root = f_root_check.isZero();
25 const x_sqrtm1 = x.mul(Fe.sqrtm1()); // x*sqrt(-1)25 const x_sqrtm1 = x.mul(Fe.sqrtm1); // x*sqrt(-1)
26 x.cMov(x_sqrtm1, @boolToInt(has_p_root) | @boolToInt(has_f_root));26 x.cMov(x_sqrtm1, @boolToInt(has_p_root) | @boolToInt(has_f_root));
27 x = x.abs();27 x = x.abs();
28 if ((@boolToInt(has_m_root) | @boolToInt(has_p_root)) == 0) {28 if ((@boolToInt(has_m_root) | @boolToInt(has_p_root)) == 0) {
...@@ -53,13 +53,13 @@ pub const Ristretto255 = struct {...@@ -53,13 +53,13 @@ pub const Ristretto255 = struct {
53 try rejectNonCanonical(s);53 try rejectNonCanonical(s);
54 const s_ = Fe.fromBytes(s);54 const s_ = Fe.fromBytes(s);
55 const ss = s_.sq(); // s^255 const ss = s_.sq(); // s^2
56 const u1_ = Fe.one().sub(ss); // (1-s^2)56 const u1_ = Fe.one.sub(ss); // (1-s^2)
57 const u1u1 = u1_.sq(); // (1-s^2)^257 const u1u1 = u1_.sq(); // (1-s^2)^2
58 const u2_ = Fe.one().add(ss); // (1+s^2)58 const u2_ = Fe.one.add(ss); // (1+s^2)
59 const u2u2 = u2_.sq(); // (1+s^2)^259 const u2u2 = u2_.sq(); // (1+s^2)^2
60 const v = Fe.edwards25519d().mul(u1u1).neg().sub(u2u2); // -(d*u1^2)-u2^260 const v = Fe.edwards25519d.mul(u1u1).neg().sub(u2u2); // -(d*u1^2)-u2^2
61 const v_u2u2 = v.mul(u2u2); // v*u2^261 const v_u2u2 = v.mul(u2u2); // v*u2^2
62 const inv_sqrt = sqrtRatioM1(Fe.one(), v_u2u2) catch |e| {62 const inv_sqrt = sqrtRatioM1(Fe.one, v_u2u2) catch |e| {
63 return error.InvalidEncoding;63 return error.InvalidEncoding;
64 };64 };
65 var x = inv_sqrt.mul(u2_);65 var x = inv_sqrt.mul(u2_);
...@@ -73,10 +73,10 @@ pub const Ristretto255 = struct {...@@ -73,10 +73,10 @@ pub const Ristretto255 = struct {
73 const p: Curve = .{73 const p: Curve = .{
74 .x = x,74 .x = x,
75 .y = y,75 .y = y,
76 .z = Fe.one(),76 .z = Fe.one,
77 .t = t,77 .t = t,
78 };78 };
79 return Ristretto255 { .p = p };79 return Ristretto255{ .p = p };
80 }80 }
8181
82 /// Encode to a Ristretto255 representative.82 /// Encode to a Ristretto255 representative.
...@@ -87,13 +87,13 @@ pub const Ristretto255 = struct {...@@ -87,13 +87,13 @@ pub const Ristretto255 = struct {
87 u1_ = u1_.mul(zmy); // (Z+Y)*(Z-Y)87 u1_ = u1_.mul(zmy); // (Z+Y)*(Z-Y)
88 const u2_ = p.x.mul(p.y); // X*Y88 const u2_ = p.x.mul(p.y); // X*Y
89 const u1_u2u2 = u2_.sq().mul(u1_); // u1*u2^289 const u1_u2u2 = u2_.sq().mul(u1_); // u1*u2^2
90 const inv_sqrt = sqrtRatioM1(Fe.one(), u1_u2u2) catch unreachable;90 const inv_sqrt = sqrtRatioM1(Fe.one, u1_u2u2) catch unreachable;
91 const den1 = inv_sqrt.mul(u1_);91 const den1 = inv_sqrt.mul(u1_);
92 const den2 = inv_sqrt.mul(u2_);92 const den2 = inv_sqrt.mul(u2_);
93 const z_inv = den1.mul(den2).mul(p.t); // den1*den2*T93 const z_inv = den1.mul(den2).mul(p.t); // den1*den2*T
94 const ix = p.x.mul(Fe.sqrtm1()); // X*sqrt(-1)94 const ix = p.x.mul(Fe.sqrtm1); // X*sqrt(-1)
95 const iy = p.y.mul(Fe.sqrtm1()); // Y*sqrt(-1)95 const iy = p.y.mul(Fe.sqrtm1); // Y*sqrt(-1)
96 const eden = den1.mul(Fe.edwards25519sqrtamd()); // den1/sqrt(a-d)96 const eden = den1.mul(Fe.edwards25519sqrtamd); // den1/sqrt(a-d)
97 const t_z_inv = p.t.mul(z_inv); // T*z_inv97 const t_z_inv = p.t.mul(z_inv); // T*z_inv
9898
99 const rotate = @boolToInt(t_z_inv.isNegative());99 const rotate = @boolToInt(t_z_inv.isNegative());
...@@ -125,23 +125,22 @@ pub const Ristretto255 = struct {...@@ -125,23 +125,22 @@ pub const Ristretto255 = struct {
125 /// Return error.WeakPublicKey if the resulting element is125 /// Return error.WeakPublicKey if the resulting element is
126 /// the identity element.126 /// the identity element.
127 pub inline fn mul(p: Ristretto255, s: [32]u8) !Ristretto255 {127 pub inline fn mul(p: Ristretto255, s: [32]u8) !Ristretto255 {
128 return Ristretto255 { .p = try p.p.mul(s) };128 return Ristretto255{ .p = try p.p.mul(s) };
129 }129 }
130};130};
131131
132test "ristretto255" {132test "ristretto255" {
133 const p = Ristretto255.basePoint();133 const p = Ristretto255.basePoint();
134 var buf: [256]u8 = undefined;134 var buf: [256]u8 = undefined;
135 const alloc = &std.heap.FixedBufferAllocator.init(&buf).allocator;135 std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{p.toBytes()}), "E2F2AE0A6ABC4E71A884A961C500515F58E30B6AA582DD8DB6A65945E08D2D76");
136 std.testing.expectEqualStrings(try std.fmt.allocPrint(alloc, "{X}", .{p.toBytes()}), "E2F2AE0A6ABC4E71A884A961C500515F58E30B6AA582DD8DB6A65945E08D2D76");
137136
138 var r: [32]u8 = undefined;137 var r: [32]u8 = undefined;
139 try fmt.hexToBytes(r[0..], "6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919");138 try fmt.hexToBytes(r[0..], "6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919");
140 var q = try Ristretto255.fromBytes(r);139 var q = try Ristretto255.fromBytes(r);
141 q = q.dbl().add(p);140 q = q.dbl().add(p);
142 std.testing.expectEqualStrings(try std.fmt.allocPrint(alloc, "{X}", .{q.toBytes()}), "E882B131016B52C1D3337080187CF768423EFCCBB517BB495AB812C4160FF44E");141 std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{q.toBytes()}), "E882B131016B52C1D3337080187CF768423EFCCBB517BB495AB812C4160FF44E");
143142
144 const s = [_]u8{15} ++ [_]u8{0} ** 31;143 const s = [_]u8{15} ++ [_]u8{0} ** 31;
145 const w = try p.mul(s);144 const w = try p.mul(s);
146 std.testing.expectEqualStrings(try std.fmt.allocPrint(alloc, "{X}", .{w.toBytes()}), "E0C418F7C8D9C4CDD7395B93EA124F3AD99021BB681DFC3302A9D99A2E53E64E");145 std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{w.toBytes()}), "E0C418F7C8D9C4CDD7395B93EA124F3AD99021BB681DFC3302A9D99A2E53E64E");
147}146}
lib/std/crypto/25519/scalar.zig+16-23
...@@ -1,20 +1,17 @@...@@ -1,20 +1,17 @@
1const std = @import("std");1const std = @import("std");
2const mem = std.mem;2const mem = std.mem;
33
4inline fn fieldSize() [32]u8 {4const field_size = [32]u8{
5 return .{5 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, // 2^252+27742317777372353535851937790883648493
6 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, // 2^252+277423177773723535358519377908836484936};
7 };
8}
97
10const ScalarExpanded = struct {8const ScalarExpanded = struct {
11 const L = fieldSize();
12 limbs: [64]i64 = [_]i64{0} ** 64,9 limbs: [64]i64 = [_]i64{0} ** 64,
1310
14 fn fromBytes(s: [32]u8) ScalarExpanded {11 fn fromBytes(s: [32]u8) ScalarExpanded {
15 var limbs: [64]i64 = undefined;12 var limbs: [64]i64 = undefined;
16 for (s) |x, idx| {13 for (s) |x, idx| {
17 limbs[idx] = @intCast(i64, x);14 limbs[idx] = @as(i64, x);
18 }15 }
19 mem.set(i64, limbs[32..], 0);16 mem.set(i64, limbs[32..], 0);
20 return .{ .limbs = limbs };17 return .{ .limbs = limbs };
...@@ -23,7 +20,7 @@ const ScalarExpanded = struct {...@@ -23,7 +20,7 @@ const ScalarExpanded = struct {
23 fn fromBytes64(s: [64]u8) ScalarExpanded {20 fn fromBytes64(s: [64]u8) ScalarExpanded {
24 var limbs: [64]i64 = undefined;21 var limbs: [64]i64 = undefined;
25 for (s) |x, idx| {22 for (s) |x, idx| {
26 limbs[idx] = @intCast(i64, x);23 limbs[idx] = @as(i64, x);
27 }24 }
28 return .{ .limbs = limbs };25 return .{ .limbs = limbs };
29 }26 }
...@@ -38,7 +35,7 @@ const ScalarExpanded = struct {...@@ -38,7 +35,7 @@ const ScalarExpanded = struct {
38 const xi = limbs[i];35 const xi = limbs[i];
39 var j = i - 32;36 var j = i - 32;
40 while (j < k) : (j += 1) {37 while (j < k) : (j += 1) {
41 const xj = limbs[j] + carry - 16 * xi * @intCast(i64, L[j - (i - 32)]);38 const xj = limbs[j] + carry - 16 * xi * @as(i64, field_size[j - (i - 32)]);
42 carry = (xj + 128) >> 8;39 carry = (xj + 128) >> 8;
43 limbs[j] = xj - carry * 256;40 limbs[j] = xj - carry * 256;
44 }41 }
...@@ -48,13 +45,13 @@ const ScalarExpanded = struct {...@@ -48,13 +45,13 @@ const ScalarExpanded = struct {
48 carry = 0;45 carry = 0;
49 comptime var j: usize = 0;46 comptime var j: usize = 0;
50 inline while (j < 32) : (j += 1) {47 inline while (j < 32) : (j += 1) {
51 const xi = limbs[j] + carry - (limbs[31] >> 4) * @intCast(i64, L[j]);48 const xi = limbs[j] + carry - (limbs[31] >> 4) * @as(i64, field_size[j]);
52 carry = xi >> 8;49 carry = xi >> 8;
53 limbs[j] = xi & 255;50 limbs[j] = xi & 255;
54 }51 }
55 j = 0;52 j = 0;
56 inline while (j < 32) : (j += 1) {53 inline while (j < 32) : (j += 1) {
57 limbs[j] -= carry * @intCast(i64, L[j]);54 limbs[j] -= carry * @as(i64, field_size[j]);
58 }55 }
59 j = 0;56 j = 0;
60 inline while (j < 32) : (j += 1) {57 inline while (j < 32) : (j += 1) {
...@@ -116,15 +113,14 @@ const ScalarExpanded = struct {...@@ -116,15 +113,14 @@ const ScalarExpanded = struct {
116113
117/// Reject a scalar whose encoding is not canonical.114/// Reject a scalar whose encoding is not canonical.
118pub fn rejectNonCanonical(s: [32]u8) !void {115pub fn rejectNonCanonical(s: [32]u8) !void {
119 const L = fieldSize();
120 var c: u8 = 0;116 var c: u8 = 0;
121 var n: u8 = 1;117 var n: u8 = 1;
122 var i: usize = 31;118 var i: usize = 31;
123 while (true) {119 while (true) {
124 const xs = @intCast(u16, s[i]);120 const xs = @as(u16, s[i]);
125 const xL = @intCast(u16, L[i]);121 const xfield_size = @as(u16, field_size[i]);
126 c |= @intCast(u8, ((xs -% xL) >> 8) & n);122 c |= @intCast(u8, ((xs -% xfield_size) >> 8) & n);
127 n &= @intCast(u8, ((xs ^ xL) -% 1) >> 8);123 n &= @intCast(u8, ((xs ^ xfield_size) -% 1) >> 8);
128 if (i == 0) break;124 if (i == 0) break;
129 i -= 1;125 i -= 1;
130 }126 }
...@@ -161,12 +157,10 @@ test "scalar25519" {...@@ -161,12 +157,10 @@ test "scalar25519" {
161 var y = x.toBytes();157 var y = x.toBytes();
162 try rejectNonCanonical(y);158 try rejectNonCanonical(y);
163 var buf: [128]u8 = undefined;159 var buf: [128]u8 = undefined;
164 const alloc = &std.heap.FixedBufferAllocator.init(&buf).allocator;160 std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{y}), "1E979B917937F3DE71D18077F961F6CEFF01030405060708010203040506070F");
165 std.testing.expectEqualStrings(try std.fmt.allocPrint(alloc, "{X}", .{y}), "1E979B917937F3DE71D18077F961F6CEFF01030405060708010203040506070F");
166161
167 const field_size = fieldSize();
168 const reduced = reduce(field_size);162 const reduced = reduce(field_size);
169 std.testing.expectEqualStrings(try std.fmt.allocPrint(alloc, "{X}", .{reduced}), "0000000000000000000000000000000000000000000000000000000000000000");163 std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{reduced}), "0000000000000000000000000000000000000000000000000000000000000000");
170}164}
171165
172test "non-canonical scalar25519" {166test "non-canonical scalar25519" {
...@@ -174,12 +168,11 @@ test "non-canonical scalar25519" {...@@ -174,12 +168,11 @@ test "non-canonical scalar25519" {
174 std.testing.expectError(error.NonCanonical, rejectNonCanonical(too_targe));168 std.testing.expectError(error.NonCanonical, rejectNonCanonical(too_targe));
175}169}
176170
177test "scalar25519 mulAdd overflow check" {171test "mulAdd overflow check" {
178 const a: [32]u8 = [_]u8{0xff} ** 32;172 const a: [32]u8 = [_]u8{0xff} ** 32;
179 const b: [32]u8 = [_]u8{0xff} ** 32;173 const b: [32]u8 = [_]u8{0xff} ** 32;
180 const c: [32]u8 = [_]u8{0xff} ** 32;174 const c: [32]u8 = [_]u8{0xff} ** 32;
181 const x = mulAdd(a, b, c);175 const x = mulAdd(a, b, c);
182 var buf: [128]u8 = undefined;176 var buf: [128]u8 = undefined;
183 const alloc = &std.heap.FixedBufferAllocator.init(&buf).allocator;177 std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{x}), "D14DF91389432C25AD60FF9791B9FD1D67BEF517D273ECCE3D9A307C1B419903");
184 std.testing.expectEqualStrings(try std.fmt.allocPrint(alloc, "{X}", .{x}), "D14DF91389432C25AD60FF9791B9FD1D67BEF517D273ECCE3D9A307C1B419903");
185}178}
lib/std/crypto/25519/x25519.zig+17-17
...@@ -56,32 +56,32 @@ test "x25519 public key calculation from secret key" {...@@ -56,32 +56,32 @@ test "x25519 public key calculation from secret key" {
56}56}
5757
58test "x25519 rfc7748 vector1" {58test "x25519 rfc7748 vector1" {
59 const secret_key = "\xa5\x46\xe3\x6b\xf0\x52\x7c\x9d\x3b\x16\x15\x4b\x82\x46\x5e\xdd\x62\x14\x4c\x0a\xc1\xfc\x5a\x18\x50\x6a\x22\x44\xba\x44\x9a\xc4";59 const secret_key = [32]u8{ 0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46, 0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4 };
60 const public_key = "\xe6\xdb\x68\x67\x58\x30\x30\xdb\x35\x94\xc1\xa4\x24\xb1\x5f\x7c\x72\x66\x24\xec\x26\xb3\x35\x3b\x10\xa9\x03\xa6\xd0\xab\x1c\x4c";60 const public_key = [32]u8{ 0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f, 0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c };
6161
62 const expected_output = "\xc3\xda\x55\x37\x9d\xe9\xc6\x90\x8e\x94\xea\x4d\xf2\x8d\x08\x4f\x32\xec\xcf\x03\x49\x1c\x71\xf7\x54\xb4\x07\x55\x77\xa2\x85\x52";62 const expected_output = [32]u8{ 0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d, 0x08, 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, 0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52 };
6363
64 var output: [32]u8 = undefined;64 var output: [32]u8 = undefined;
6565
66 std.testing.expect(X25519.create(output[0..], secret_key, public_key));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));67 std.testing.expect(std.mem.eql(u8, &output, expected_output[0..]));
68}68}
6969
70test "x25519 rfc7748 vector2" {70test "x25519 rfc7748 vector2" {
71 const secret_key = "\x4b\x66\xe9\xd4\xd1\xb4\x67\x3c\x5a\xd2\x26\x91\x95\x7d\x6a\xf5\xc1\x1b\x64\x21\xe0\xea\x01\xd4\x2c\xa4\x16\x9e\x79\x18\xba\x0d";71 const secret_key = [32]u8{ 0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26, 0x91, 0x95, 0x7d, 0x6a, 0xf5, 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, 0x01, 0xd4, 0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18, 0xba, 0x0d };
72 const public_key = "\xe5\x21\x0f\x12\x78\x68\x11\xd3\xf4\xb7\x95\x9d\x05\x38\xae\x2c\x31\xdb\xe7\x10\x6f\xc0\x3c\x3e\xfc\x4c\xd5\x49\xc7\x15\xa4\x93";72 const public_key = [32]u8{ 0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, 0xf4, 0xb7, 0x95, 0x9d, 0x05, 0x38, 0xae, 0x2c, 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0, 0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93 };
7373
74 const expected_output = "\x95\xcb\xde\x94\x76\xe8\x90\x7d\x7a\xad\xe4\x5c\xb4\xb8\x73\xf8\x8b\x59\x5a\x68\x79\x9f\xa1\x52\xe6\xf8\xf7\x64\x7a\xac\x79\x57";74 const expected_output = [32]u8{ 0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4, 0x5c, 0xb4, 0xb8, 0x73, 0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, 0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57 };
7575
76 var output: [32]u8 = undefined;76 var output: [32]u8 = undefined;
7777
78 std.testing.expect(X25519.create(output[0..], secret_key, public_key));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));79 std.testing.expect(std.mem.eql(u8, &output, expected_output[0..]));
80}80}
8181
82test "x25519 rfc7748 one iteration" {82test "x25519 rfc7748 one iteration" {
83 const initial_value = "\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".*;83 const initial_value = [32]u8{ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
84 const expected_output = "\x42\x2c\x8e\x7a\x62\x27\xd7\xbc\xa1\x35\x0b\x3e\x2b\xb7\x27\x9f\x78\x97\xb8\x7b\xb6\x85\x4b\x78\x3c\x60\xe8\x03\x11\xae\x30\x79";84 const expected_output = [32]u8{ 0x42, 0x2c, 0x8e, 0x7a, 0x62, 0x27, 0xd7, 0xbc, 0xa1, 0x35, 0x0b, 0x3e, 0x2b, 0xb7, 0x27, 0x9f, 0x78, 0x97, 0xb8, 0x7b, 0xb6, 0x85, 0x4b, 0x78, 0x3c, 0x60, 0xe8, 0x03, 0x11, 0xae, 0x30, 0x79 };
8585
86 var k: [32]u8 = initial_value;86 var k: [32]u8 = initial_value;
87 var u: [32]u8 = initial_value;87 var u: [32]u8 = initial_value;
...@@ -95,7 +95,7 @@ test "x25519 rfc7748 one iteration" {...@@ -95,7 +95,7 @@ test "x25519 rfc7748 one iteration" {
95 std.mem.copy(u8, k[0..], output[0..]);95 std.mem.copy(u8, k[0..], output[0..]);
96 }96 }
9797
98 std.testing.expect(std.mem.eql(u8, k[0..], expected_output));98 std.testing.expect(std.mem.eql(u8, k[0..], expected_output[0..]));
99}99}
100100
101test "x25519 rfc7748 1,000 iterations" {101test "x25519 rfc7748 1,000 iterations" {
...@@ -104,8 +104,8 @@ test "x25519 rfc7748 1,000 iterations" {...@@ -104,8 +104,8 @@ test "x25519 rfc7748 1,000 iterations" {
104 return error.SkipZigTest;104 return error.SkipZigTest;
105 }105 }
106106
107 const initial_value = "\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";107 const initial_value = [32]u8{ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
108 const expected_output = "\x68\x4c\xf5\x9b\xa8\x33\x09\x55\x28\x00\xef\x56\x6f\x2f\x4d\x3c\x1c\x38\x87\xc4\x93\x60\xe3\x87\x5f\x2e\xb9\x4d\x99\x53\x2c\x51";108 const expected_output = [32]u8{ 0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55, 0x28, 0x00, 0xef, 0x56, 0x6f, 0x2f, 0x4d, 0x3c, 0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60, 0xe3, 0x87, 0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51 };
109109
110 var k: [32]u8 = initial_value.*;110 var k: [32]u8 = initial_value.*;
111 var u: [32]u8 = initial_value.*;111 var u: [32]u8 = initial_value.*;
...@@ -127,8 +127,8 @@ test "x25519 rfc7748 1,000,000 iterations" {...@@ -127,8 +127,8 @@ test "x25519 rfc7748 1,000,000 iterations" {
127 return error.SkipZigTest;127 return error.SkipZigTest;
128 }128 }
129129
130 const initial_value = "\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";130 const initial_value = [32]u8{ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
131 const expected_output = "\x7c\x39\x11\xe0\xab\x25\x86\xfd\x86\x44\x97\x29\x7e\x57\x5e\x6f\x3b\xc6\x01\xc0\x88\x3c\x30\xdf\x5f\x4d\xd2\xd2\x4f\x66\x54\x24";131 const expected_output = [32]u8{ 0x7c, 0x39, 0x11, 0xe0, 0xab, 0x25, 0x86, 0xfd, 0x86, 0x44, 0x97, 0x29, 0x7e, 0x57, 0x5e, 0x6f, 0x3b, 0xc6, 0x01, 0xc0, 0x88, 0x3c, 0x30, 0xdf, 0x5f, 0x4d, 0xd2, 0xd2, 0x4f, 0x66, 0x54, 0x24 };
132132
133 var k: [32]u8 = initial_value.*;133 var k: [32]u8 = initial_value.*;
134 var u: [32]u8 = initial_value.*;134 var u: [32]u8 = initial_value.*;