authorgravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-08-31 18:40:09+12:00
committergravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-08-31 18:40:09+12:00
loga7527389ccdf4e3ab6ce3f83ff9a55003b2c5692
treebadc8a288b9121227e0be06955587a832eee5efb
parent65b89f598c63719ab80553163424feb2d8e6f9e4

Make poly1305 and x25519 more idiomatic zig

This also adjusts the current hash/hmac functions to have a consistent interface allowing easier switching/testing.

9 files changed, 387 insertions(+), 350 deletions(-)

std/crypto/blake2.zig+8-8
...@@ -34,8 +34,8 @@ pub const Blake2s256 = Blake2s(256);...@@ -34,8 +34,8 @@ pub const Blake2s256 = Blake2s(256);
34fn Blake2s(comptime out_len: usize) type {34fn Blake2s(comptime out_len: usize) type {
35 return struct {35 return struct {
36 const Self = this;36 const Self = this;
37 const block_size = 64;37 const block_length = 64;
38 const digest_size = out_len / 8;38 const digest_length = out_len / 8;
3939
40 const iv = [8]u32{40 const iv = [8]u32{
41 0x6A09E667,41 0x6A09E667,
...@@ -250,8 +250,8 @@ test "blake2s256 streaming" {...@@ -250,8 +250,8 @@ test "blake2s256 streaming" {
250}250}
251251
252test "blake2s256 aligned final" {252test "blake2s256 aligned final" {
253 var block = []u8{0} ** Blake2s256.block_size;253 var block = []u8{0} ** Blake2s256.block_length;
254 var out: [Blake2s256.digest_size]u8 = undefined;254 var out: [Blake2s256.digest_length]u8 = undefined;
255255
256 var h = Blake2s256.init();256 var h = Blake2s256.init();
257 h.update(block);257 h.update(block);
...@@ -267,8 +267,8 @@ pub const Blake2b512 = Blake2b(512);...@@ -267,8 +267,8 @@ pub const Blake2b512 = Blake2b(512);
267fn Blake2b(comptime out_len: usize) type {267fn Blake2b(comptime out_len: usize) type {
268 return struct {268 return struct {
269 const Self = this;269 const Self = this;
270 const block_size = 128;270 const block_length = 128;
271 const digest_size = out_len / 8;271 const digest_length = out_len / 8;
272272
273 const iv = [8]u64{273 const iv = [8]u64{
274 0x6a09e667f3bcc908,274 0x6a09e667f3bcc908,
...@@ -483,8 +483,8 @@ test "blake2b512 streaming" {...@@ -483,8 +483,8 @@ test "blake2b512 streaming" {
483}483}
484484
485test "blake2b512 aligned final" {485test "blake2b512 aligned final" {
486 var block = []u8{0} ** Blake2b512.block_size;486 var block = []u8{0} ** Blake2b512.block_length;
487 var out: [Blake2b512.digest_size]u8 = undefined;487 var out: [Blake2b512.digest_length]u8 = undefined;
488488
489 var h = Blake2b512.init();489 var h = Blake2b512.init();
490 h.update(block);490 h.update(block);
std/crypto/hmac.zig+54-37
...@@ -7,46 +7,63 @@ pub const HmacMd5 = Hmac(crypto.Md5);...@@ -7,46 +7,63 @@ pub const HmacMd5 = Hmac(crypto.Md5);
7pub const HmacSha1 = Hmac(crypto.Sha1);7pub const HmacSha1 = Hmac(crypto.Sha1);
8pub const HmacSha256 = Hmac(crypto.Sha256);8pub const HmacSha256 = Hmac(crypto.Sha256);
99
10pub fn Hmac(comptime H: type) type {10pub fn Hmac(comptime Hash: type) type {
11 return struct {11 return struct {
12 const digest_size = H.digest_size;12 const Self = this;
13 pub const mac_length = Hash.digest_length;
14 pub const minimum_key_length = 0;
1315
14 pub fn hash(output: []u8, key: []const u8, message: []const u8) void {16 o_key_pad: [Hash.block_length]u8,
15 debug.assert(output.len >= H.digest_size);17 i_key_pad: [Hash.block_length]u8,
16 debug.assert(H.digest_size <= H.block_size); // HMAC makes this assumption18 scratch: [Hash.block_length]u8,
17 var scratch: [H.block_size]u8 = undefined;19 hash: Hash,
20
21 // HMAC(k, m) = H(o_key_pad | H(i_key_pad | msg)) where | is concatenation
22 pub fn create(out: []u8, msg: []const u8, key: []const u8) void {
23 var ctx = Self.init(key);
24 ctx.update(msg);
25 ctx.final(out[0..]);
26 }
27
28 pub fn init(key: []const u8) Self {
29 var ctx: Self = undefined;
1830
19 // Normalize key length to block size of hash31 // Normalize key length to block size of hash
20 if (key.len > H.block_size) {32 if (key.len > Hash.block_length) {
21 H.hash(key, scratch[0..H.digest_size]);33 Hash.hash(key, ctx.scratch[0..mac_length]);
22 mem.set(u8, scratch[H.digest_size..H.block_size], 0);34 mem.set(u8, ctx.scratch[mac_length..Hash.block_length], 0);
23 } else if (key.len < H.block_size) {35 } else if (key.len < Hash.block_length) {
24 mem.copy(u8, scratch[0..key.len], key);36 mem.copy(u8, ctx.scratch[0..key.len], key);
25 mem.set(u8, scratch[key.len..H.block_size], 0);37 mem.set(u8, ctx.scratch[key.len..Hash.block_length], 0);
26 } else {38 } else {
27 mem.copy(u8, scratch[0..], key);39 mem.copy(u8, ctx.scratch[0..], key);
28 }40 }
2941
30 var o_key_pad: [H.block_size]u8 = undefined;42 for (ctx.o_key_pad) |*b, i| {
31 for (o_key_pad) |*b, i| {43 b.* = ctx.scratch[i] ^ 0x5c;
32 b.* = scratch[i] ^ 0x5c;
33 }44 }
3445
35 var i_key_pad: [H.block_size]u8 = undefined;46 for (ctx.i_key_pad) |*b, i| {
36 for (i_key_pad) |*b, i| {47 b.* = ctx.scratch[i] ^ 0x36;
37 b.* = scratch[i] ^ 0x36;
38 }48 }
3949
40 // HMAC(k, m) = H(o_key_pad | H(i_key_pad | message)) where | is concatenation50 ctx.hash = Hash.init();
41 var hmac = H.init();51 ctx.hash.update(ctx.i_key_pad[0..]);
42 hmac.update(i_key_pad[0..]);52 return ctx;
43 hmac.update(message);53 }
44 hmac.final(scratch[0..H.digest_size]);54
55 pub fn update(ctx: *Self, msg: []const u8) void {
56 ctx.hash.update(msg);
57 }
58
59 pub fn final(ctx: *Self, out: []u8) void {
60 debug.assert(Hash.block_length >= out.len and out.len >= mac_length);
4561
46 hmac.reset();62 ctx.hash.final(ctx.scratch[0..mac_length]);
47 hmac.update(o_key_pad[0..]);63 ctx.hash.reset();
48 hmac.update(scratch[0..H.digest_size]);64 ctx.hash.update(ctx.o_key_pad[0..]);
49 hmac.final(output[0..H.digest_size]);65 ctx.hash.update(ctx.scratch[0..mac_length]);
66 ctx.hash.final(out[0..mac_length]);
50 }67 }
51 };68 };
52}69}
...@@ -54,28 +71,28 @@ pub fn Hmac(comptime H: type) type {...@@ -54,28 +71,28 @@ pub fn Hmac(comptime H: type) type {
54const htest = @import("test.zig");71const htest = @import("test.zig");
5572
56test "hmac md5" {73test "hmac md5" {
57 var out: [crypto.Md5.digest_size]u8 = undefined;74 var out: [HmacMd5.mac_length]u8 = undefined;
58 HmacMd5.hash(out[0..], "", "");75 HmacMd5.create(out[0..], "", "");
59 htest.assertEqual("74e6f7298a9c2d168935f58c001bad88", out[0..]);76 htest.assertEqual("74e6f7298a9c2d168935f58c001bad88", out[0..]);
6077
61 HmacMd5.hash(out[0..], "key", "The quick brown fox jumps over the lazy dog");78 HmacMd5.create(out[0..], "The quick brown fox jumps over the lazy dog", "key");
62 htest.assertEqual("80070713463e7749b90c2dc24911e275", out[0..]);79 htest.assertEqual("80070713463e7749b90c2dc24911e275", out[0..]);
63}80}
6481
65test "hmac sha1" {82test "hmac sha1" {
66 var out: [crypto.Sha1.digest_size]u8 = undefined;83 var out: [HmacSha1.mac_length]u8 = undefined;
67 HmacSha1.hash(out[0..], "", "");84 HmacSha1.create(out[0..], "", "");
68 htest.assertEqual("fbdb1d1b18aa6c08324b7d64b71fb76370690e1d", out[0..]);85 htest.assertEqual("fbdb1d1b18aa6c08324b7d64b71fb76370690e1d", out[0..]);
6986
70 HmacSha1.hash(out[0..], "key", "The quick brown fox jumps over the lazy dog");87 HmacSha1.create(out[0..], "The quick brown fox jumps over the lazy dog", "key");
71 htest.assertEqual("de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9", out[0..]);88 htest.assertEqual("de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9", out[0..]);
72}89}
7390
74test "hmac sha256" {91test "hmac sha256" {
75 var out: [crypto.Sha256.digest_size]u8 = undefined;92 var out: [HmacSha256.mac_length]u8 = undefined;
76 HmacSha256.hash(out[0..], "", "");93 HmacSha256.create(out[0..], "", "");
77 htest.assertEqual("b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad", out[0..]);94 htest.assertEqual("b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad", out[0..]);
7895
79 HmacSha256.hash(out[0..], "key", "The quick brown fox jumps over the lazy dog");96 HmacSha256.create(out[0..], "The quick brown fox jumps over the lazy dog", "key");
80 htest.assertEqual("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8", out[0..]);97 htest.assertEqual("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8", out[0..]);
81}98}
std/crypto/index.zig+4-4
...@@ -21,15 +21,15 @@ pub const Blake2b512 = blake2.Blake2b512;...@@ -21,15 +21,15 @@ pub const Blake2b512 = blake2.Blake2b512;
2121
22const hmac = @import("hmac.zig");22const hmac = @import("hmac.zig");
23pub const HmacMd5 = hmac.HmacMd5;23pub const HmacMd5 = hmac.HmacMd5;
24pub const HmacSha1 = hmac.Sha1;24pub const HmacSha1 = hmac.HmacSha1;
25pub const HmacSha256 = hmac.Sha256;25pub const HmacSha256 = hmac.HmacSha256;
2626
27const import_chaCha20 = @import("chacha20.zig");27const import_chaCha20 = @import("chacha20.zig");
28pub const chaCha20IETF = import_chaCha20.chaCha20IETF;28pub const chaCha20IETF = import_chaCha20.chaCha20IETF;
29pub const chaCha20With64BitNonce = import_chaCha20.chaCha20With64BitNonce;29pub const chaCha20With64BitNonce = import_chaCha20.chaCha20With64BitNonce;
3030
31const poly1305 = @import("poly1305.zig");31pub const Poly1305 = @import("poly1305.zig").Poly1305;
32const x25519 = @import("x25519.zig");32pub const X25519 = @import("x25519.zig").X25519;
3333
34test "crypto" {34test "crypto" {
35 _ = @import("md5.zig");35 _ = @import("md5.zig");
std/crypto/md5.zig+4-4
...@@ -29,8 +29,8 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundPar...@@ -29,8 +29,8 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundPar
2929
30pub const Md5 = struct {30pub const Md5 = struct {
31 const Self = this;31 const Self = this;
32 const block_size = 64;32 const block_length = 64;
33 const digest_size = 16;33 const digest_length = 16;
3434
35 s: [4]u32,35 s: [4]u32,
36 // Streaming Cache36 // Streaming Cache
...@@ -271,8 +271,8 @@ test "md5 streaming" {...@@ -271,8 +271,8 @@ test "md5 streaming" {
271}271}
272272
273test "md5 aligned final" {273test "md5 aligned final" {
274 var block = []u8{0} ** Md5.block_size;274 var block = []u8{0} ** Md5.block_length;
275 var out: [Md5.digest_size]u8 = undefined;275 var out: [Md5.digest_length]u8 = undefined;
276276
277 var h = Md5.init();277 var h = Md5.init();
278 h.update(block);278 h.update(block);
std/crypto/poly1305.zig+179-166
...@@ -9,7 +9,12 @@ const Endian = builtin.Endian;...@@ -9,7 +9,12 @@ const Endian = builtin.Endian;
9const readInt = std.mem.readInt;9const readInt = std.mem.readInt;
10const writeInt = std.mem.writeInt;10const writeInt = std.mem.writeInt;
1111
12const crypto_poly1305_ctx = struct {12pub const Poly1305 = struct {
13 const Self = this;
14
15 pub const mac_length = 16;
16 pub const minimum_key_length = 32;
17
13 // constant multiplier (from the secret key)18 // constant multiplier (from the secret key)
14 r: [4]u32,19 r: [4]u32,
15 // accumulated hash20 // accumulated hash
...@@ -21,190 +26,198 @@ const crypto_poly1305_ctx = struct {...@@ -21,190 +26,198 @@ const crypto_poly1305_ctx = struct {
21 // How many bytes are there in the chunk.26 // How many bytes are there in the chunk.
22 c_idx: usize,27 c_idx: usize,
2328
24 fn secure_zero(self: *crypto_poly1305_ctx) void {29 fn secure_zero(self: *Poly1305) void {
25 std.mem.secureZero(u8, @ptrCast([*]u8, self)[0..@sizeOf(crypto_poly1305_ctx)]);30 std.mem.secureZero(u8, @ptrCast([*]u8, self)[0..@sizeOf(Poly1305)]);
26 }31 }
27};
2832
29// h = (h + c) * r33 pub fn create(out: []u8, msg: []const u8, key: []const u8) void {
30// preconditions:34 std.debug.assert(out.len >= mac_length);
31// ctx->h <= 4_ffffffff_ffffffff_ffffffff_ffffffff35 std.debug.assert(key.len >= minimum_key_length);
32// ctx->c <= 1_ffffffff_ffffffff_ffffffff_ffffffff
33// ctx->r <= 0ffffffc_0ffffffc_0ffffffc_0fffffff
34// Postcondition:
35// ctx->h <= 4_ffffffff_ffffffff_ffffffff_ffffffff
36fn poly_block(ctx: *crypto_poly1305_ctx) void {
37 // s = h + c, without carry propagation
38 const s0 = u64(ctx.h[0]) + ctx.c[0]; // s0 <= 1_fffffffe
39 const s1 = u64(ctx.h[1]) + ctx.c[1]; // s1 <= 1_fffffffe
40 const s2 = u64(ctx.h[2]) + ctx.c[2]; // s2 <= 1_fffffffe
41 const s3 = u64(ctx.h[3]) + ctx.c[3]; // s3 <= 1_fffffffe
42 const s4 = u64(ctx.h[4]) + ctx.c[4]; // s4 <= 5
43
44 // Local all the things!
45 const r0 = ctx.r[0]; // r0 <= 0fffffff
46 const r1 = ctx.r[1]; // r1 <= 0ffffffc
47 const r2 = ctx.r[2]; // r2 <= 0ffffffc
48 const r3 = ctx.r[3]; // r3 <= 0ffffffc
49 const rr0 = (r0 >> 2) * 5; // rr0 <= 13fffffb // lose 2 bits...
50 const rr1 = (r1 >> 2) + r1; // rr1 <= 13fffffb // rr1 == (r1 >> 2) * 5
51 const rr2 = (r2 >> 2) + r2; // rr2 <= 13fffffb // rr1 == (r2 >> 2) * 5
52 const rr3 = (r3 >> 2) + r3; // rr3 <= 13fffffb // rr1 == (r3 >> 2) * 5
53
54 // (h + c) * r, without carry propagation
55 const x0 = s0 * r0 + s1 * rr3 + s2 * rr2 + s3 * rr1 + s4 * rr0; //<=97ffffe007fffff8
56 const x1 = s0 * r1 + s1 * r0 + s2 * rr3 + s3 * rr2 + s4 * rr1; //<=8fffffe20ffffff6
57 const x2 = s0 * r2 + s1 * r1 + s2 * r0 + s3 * rr3 + s4 * rr2; //<=87ffffe417fffff4
58 const x3 = s0 * r3 + s1 * r2 + s2 * r1 + s3 * r0 + s4 * rr3; //<=7fffffe61ffffff2
59 const x4 = s4 * (r0 & 3); // ...recover 2 bits //<= f
60
61 // partial reduction modulo 2^130 - 5
62 const _u5 = @truncate(u32, x4 + (x3 >> 32)); // u5 <= 7ffffff5
63 const _u0 = (_u5 >> 2) * 5 + (x0 & 0xffffffff);
64 const _u1 = (_u0 >> 32) + (x1 & 0xffffffff) + (x0 >> 32);
65 const _u2 = (_u1 >> 32) + (x2 & 0xffffffff) + (x1 >> 32);
66 const _u3 = (_u2 >> 32) + (x3 & 0xffffffff) + (x2 >> 32);
67 const _u4 = (_u3 >> 32) + (_u5 & 3);
68
69 // Update the hash
70 ctx.h[0] = @truncate(u32, _u0); // u0 <= 1_9ffffff0
71 ctx.h[1] = @truncate(u32, _u1); // u1 <= 1_97ffffe0
72 ctx.h[2] = @truncate(u32, _u2); // u2 <= 1_8fffffe2
73 ctx.h[3] = @truncate(u32, _u3); // u3 <= 1_87ffffe4
74 ctx.h[4] = @truncate(u32, _u4); // u4 <= 4
75}
76
77// (re-)initializes the input counter and input buffer
78fn poly_clear_c(ctx: *crypto_poly1305_ctx) void {
79 ctx.c[0] = 0;
80 ctx.c[1] = 0;
81 ctx.c[2] = 0;
82 ctx.c[3] = 0;
83 ctx.c_idx = 0;
84}
8536
86fn poly_take_input(ctx: *crypto_poly1305_ctx, input: u8) void {37 var ctx = Poly1305.init(key);
87 const word = ctx.c_idx >> 2;38 ctx.update(msg);
88 const byte = ctx.c_idx & 3;39 ctx.final(out);
89 ctx.c[word] |= std.math.shl(u32, input, byte * 8);
90 ctx.c_idx += 1;
91}
92
93fn poly_update(ctx: *crypto_poly1305_ctx, message: []const u8) void {
94 for (message) |b| {
95 poly_take_input(ctx, b);
96 if (ctx.c_idx == 16) {
97 poly_block(ctx);
98 poly_clear_c(ctx);
99 }
100 }40 }
101}
10241
103pub fn crypto_poly1305_init(ctx: *crypto_poly1305_ctx, key: [32]u8) void {42 // Initialize the MAC context.
104 // Initial hash is zero43 // - key.len is sufficient size.
105 {44 pub fn init(key: []const u8) Self {
106 var i: usize = 0;45 var ctx: Poly1305 = undefined;
107 while (i < 5) : (i += 1) {46
108 ctx.h[i] = 0;47 // Initial hash is zero
48 {
49 var i: usize = 0;
50 while (i < 5) : (i += 1) {
51 ctx.h[i] = 0;
52 }
109 }53 }
110 }54 // add 2^130 to every input block
111 // add 2^130 to every input block55 ctx.c[4] = 1;
112 ctx.c[4] = 1;56 poly_clear_c(&ctx);
113 poly_clear_c(ctx);57
11458 // load r and pad (r has some of its bits cleared)
115 // load r and pad (r has some of its bits cleared)59 {
116 {60 var i: usize = 0;
117 var i: usize = 0;61 while (i < 1) : (i += 1) {
118 while (i < 1) : (i += 1) {62 ctx.r[0] = readInt(key[0..4], u32, Endian.Little) & 0x0fffffff;
119 ctx.r[0] = readInt(key[0..4], u32, Endian.Little) & 0x0fffffff;63 }
120 }64 }
121 }65 {
122 {66 var i: usize = 1;
123 var i: usize = 1;67 while (i < 4) : (i += 1) {
124 while (i < 4) : (i += 1) {68 ctx.r[i] = readInt(key[i * 4 .. i * 4 + 4], u32, Endian.Little) & 0x0ffffffc;
125 ctx.r[i] = readInt(key[i * 4 .. i * 4 + 4], u32, Endian.Little) & 0x0ffffffc;69 }
126 }70 }
127 }71 {
128 {72 var i: usize = 0;
129 var i: usize = 0;73 while (i < 4) : (i += 1) {
130 while (i < 4) : (i += 1) {74 ctx.pad[i] = readInt(key[i * 4 + 16 .. i * 4 + 16 + 4], u32, Endian.Little);
131 ctx.pad[i] = readInt(key[i * 4 + 16 .. i * 4 + 16 + 4], u32, Endian.Little);75 }
132 }76 }
77
78 return ctx;
133 }79 }
134}
13580
136inline fn alignto(x: usize, block_size: usize) usize {81 // h = (h + c) * r
137 return ((~x) +% 1) & (block_size - 1);82 // preconditions:
138}83 // ctx->h <= 4_ffffffff_ffffffff_ffffffff_ffffffff
84 // ctx->c <= 1_ffffffff_ffffffff_ffffffff_ffffffff
85 // ctx->r <= 0ffffffc_0ffffffc_0ffffffc_0fffffff
86 // Postcondition:
87 // ctx->h <= 4_ffffffff_ffffffff_ffffffff_ffffffff
88 fn poly_block(ctx: *Poly1305) void {
89 // s = h + c, without carry propagation
90 const s0 = u64(ctx.h[0]) + ctx.c[0]; // s0 <= 1_fffffffe
91 const s1 = u64(ctx.h[1]) + ctx.c[1]; // s1 <= 1_fffffffe
92 const s2 = u64(ctx.h[2]) + ctx.c[2]; // s2 <= 1_fffffffe
93 const s3 = u64(ctx.h[3]) + ctx.c[3]; // s3 <= 1_fffffffe
94 const s4 = u64(ctx.h[4]) + ctx.c[4]; // s4 <= 5
95
96 // Local all the things!
97 const r0 = ctx.r[0]; // r0 <= 0fffffff
98 const r1 = ctx.r[1]; // r1 <= 0ffffffc
99 const r2 = ctx.r[2]; // r2 <= 0ffffffc
100 const r3 = ctx.r[3]; // r3 <= 0ffffffc
101 const rr0 = (r0 >> 2) * 5; // rr0 <= 13fffffb // lose 2 bits...
102 const rr1 = (r1 >> 2) + r1; // rr1 <= 13fffffb // rr1 == (r1 >> 2) * 5
103 const rr2 = (r2 >> 2) + r2; // rr2 <= 13fffffb // rr1 == (r2 >> 2) * 5
104 const rr3 = (r3 >> 2) + r3; // rr3 <= 13fffffb // rr1 == (r3 >> 2) * 5
105
106 // (h + c) * r, without carry propagation
107 const x0 = s0 * r0 + s1 * rr3 + s2 * rr2 + s3 * rr1 + s4 * rr0; //<=97ffffe007fffff8
108 const x1 = s0 * r1 + s1 * r0 + s2 * rr3 + s3 * rr2 + s4 * rr1; //<=8fffffe20ffffff6
109 const x2 = s0 * r2 + s1 * r1 + s2 * r0 + s3 * rr3 + s4 * rr2; //<=87ffffe417fffff4
110 const x3 = s0 * r3 + s1 * r2 + s2 * r1 + s3 * r0 + s4 * rr3; //<=7fffffe61ffffff2
111 const x4 = s4 * (r0 & 3); // ...recover 2 bits //<= f
112
113 // partial reduction modulo 2^130 - 5
114 const _u5 = @truncate(u32, x4 + (x3 >> 32)); // u5 <= 7ffffff5
115 const _u0 = (_u5 >> 2) * 5 + (x0 & 0xffffffff);
116 const _u1 = (_u0 >> 32) + (x1 & 0xffffffff) + (x0 >> 32);
117 const _u2 = (_u1 >> 32) + (x2 & 0xffffffff) + (x1 >> 32);
118 const _u3 = (_u2 >> 32) + (x3 & 0xffffffff) + (x2 >> 32);
119 const _u4 = (_u3 >> 32) + (_u5 & 3);
120
121 // Update the hash
122 ctx.h[0] = @truncate(u32, _u0); // u0 <= 1_9ffffff0
123 ctx.h[1] = @truncate(u32, _u1); // u1 <= 1_97ffffe0
124 ctx.h[2] = @truncate(u32, _u2); // u2 <= 1_8fffffe2
125 ctx.h[3] = @truncate(u32, _u3); // u3 <= 1_87ffffe4
126 ctx.h[4] = @truncate(u32, _u4); // u4 <= 4
127 }
139128
140pub fn crypto_poly1305_update(ctx: *crypto_poly1305_ctx, message: []const u8) void {129 // (re-)initializes the input counter and input buffer
141 // Align ourselves with block boundaries130 fn poly_clear_c(ctx: *Poly1305) void {
142 const alignm = std.math.min(alignto(ctx.c_idx, 16), message.len);131 ctx.c[0] = 0;
143 poly_update(ctx, message[0..alignm]);132 ctx.c[1] = 0;
144133 ctx.c[2] = 0;
145 var nmessage = message[alignm..];134 ctx.c[3] = 0;
146135 ctx.c_idx = 0;
147 // Process the message block by block
148 const nb_blocks = nmessage.len >> 4;
149 var i: usize = 0;
150 while (i < nb_blocks) : (i += 1) {
151 ctx.c[0] = readInt(nmessage[0..4], u32, Endian.Little);
152 ctx.c[1] = readInt(nmessage[4..8], u32, Endian.Little);
153 ctx.c[2] = readInt(nmessage[8..12], u32, Endian.Little);
154 ctx.c[3] = readInt(nmessage[12..16], u32, Endian.Little);
155 poly_block(ctx);
156 nmessage = nmessage[16..];
157 }136 }
158 if (nb_blocks > 0) {137
159 poly_clear_c(ctx);138 fn poly_take_input(ctx: *Poly1305, input: u8) void {
139 const word = ctx.c_idx >> 2;
140 const byte = ctx.c_idx & 3;
141 ctx.c[word] |= std.math.shl(u32, input, byte * 8);
142 ctx.c_idx += 1;
160 }143 }
161144
162 // remaining bytes145 fn poly_update(ctx: *Poly1305, msg: []const u8) void {
163 poly_update(ctx, nmessage[0..]);146 for (msg) |b| {
164}147 poly_take_input(ctx, b);
148 if (ctx.c_idx == 16) {
149 poly_block(ctx);
150 poly_clear_c(ctx);
151 }
152 }
153 }
165154
166pub fn crypto_poly1305_final(ctx: *crypto_poly1305_ctx, mac: []u8) void {155 inline fn alignto(x: usize, block_size: usize) usize {
167 // Process the last block (if any)156 return ((~x) +% 1) & (block_size - 1);
168 if (ctx.c_idx != 0) {
169 // move the final 1 according to remaining input length
170 // (We may add less than 2^130 to the last input block)
171 ctx.c[4] = 0;
172 poly_take_input(ctx, 1);
173 // one last hash update
174 poly_block(ctx);
175 }157 }
176158
177 // check if we should subtract 2^130-5 by performing the159 // Feed data into the MAC context.
178 // corresponding carry propagation.160 pub fn update(ctx: *Self, msg: []const u8) void {
179 const _u0 = u64(5) + ctx.h[0]; // <= 1_00000004161 // Align ourselves with block boundaries
180 const _u1 = (_u0 >> 32) + ctx.h[1]; // <= 1_00000000162 const alignm = std.math.min(alignto(ctx.c_idx, 16), msg.len);
181 const _u2 = (_u1 >> 32) + ctx.h[2]; // <= 1_00000000163 poly_update(ctx, msg[0..alignm]);
182 const _u3 = (_u2 >> 32) + ctx.h[3]; // <= 1_00000000
183 const _u4 = (_u3 >> 32) + ctx.h[4]; // <= 5
184 // u4 indicates how many times we should subtract 2^130-5 (0 or 1)
185
186 // h + pad, minus 2^130-5 if u4 exceeds 3
187 const uu0 = (_u4 >> 2) * 5 + ctx.h[0] + ctx.pad[0]; // <= 2_00000003
188 const uu1 = (uu0 >> 32) + ctx.h[1] + ctx.pad[1]; // <= 2_00000000
189 const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000
190 const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000
191
192 writeInt(mac[0..], uu0, Endian.Little);
193 writeInt(mac[4..], uu1, Endian.Little);
194 writeInt(mac[8..], uu2, Endian.Little);
195 writeInt(mac[12..], uu3, Endian.Little);
196
197 ctx.secure_zero();
198}
199164
200pub fn crypto_poly1305(mac: []u8, message: []const u8, key: [32]u8) void {165 var nmsg = msg[alignm..];
201 std.debug.assert(mac.len >= 16);
202166
203 var ctx: crypto_poly1305_ctx = undefined;167 // Process the msg block by block
204 crypto_poly1305_init(&ctx, key);168 const nb_blocks = nmsg.len >> 4;
205 crypto_poly1305_update(&ctx, message);169 var i: usize = 0;
206 crypto_poly1305_final(&ctx, mac);170 while (i < nb_blocks) : (i += 1) {
207}171 ctx.c[0] = readInt(nmsg[0..4], u32, Endian.Little);
172 ctx.c[1] = readInt(nmsg[4..8], u32, Endian.Little);
173 ctx.c[2] = readInt(nmsg[8..12], u32, Endian.Little);
174 ctx.c[3] = readInt(nmsg[12..16], u32, Endian.Little);
175 poly_block(ctx);
176 nmsg = nmsg[16..];
177 }
178 if (nb_blocks > 0) {
179 poly_clear_c(ctx);
180 }
181
182 // remaining bytes
183 poly_update(ctx, nmsg[0..]);
184 }
185
186 // Finalize the MAC and output into buffer provided by caller.
187 pub fn final(ctx: *Self, out: []u8) void {
188 // Process the last block (if any)
189 if (ctx.c_idx != 0) {
190 // move the final 1 according to remaining input length
191 // (We may add less than 2^130 to the last input block)
192 ctx.c[4] = 0;
193 poly_take_input(ctx, 1);
194 // one last hash update
195 poly_block(ctx);
196 }
197
198 // check if we should subtract 2^130-5 by performing the
199 // corresponding carry propagation.
200 const _u0 = u64(5) + ctx.h[0]; // <= 1_00000004
201 const _u1 = (_u0 >> 32) + ctx.h[1]; // <= 1_00000000
202 const _u2 = (_u1 >> 32) + ctx.h[2]; // <= 1_00000000
203 const _u3 = (_u2 >> 32) + ctx.h[3]; // <= 1_00000000
204 const _u4 = (_u3 >> 32) + ctx.h[4]; // <= 5
205 // u4 indicates how many times we should subtract 2^130-5 (0 or 1)
206
207 // h + pad, minus 2^130-5 if u4 exceeds 3
208 const uu0 = (_u4 >> 2) * 5 + ctx.h[0] + ctx.pad[0]; // <= 2_00000003
209 const uu1 = (uu0 >> 32) + ctx.h[1] + ctx.pad[1]; // <= 2_00000000
210 const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000
211 const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000
212
213 writeInt(out[0..], @truncate(u32, uu0), Endian.Little);
214 writeInt(out[4..], @truncate(u32, uu1), Endian.Little);
215 writeInt(out[8..], @truncate(u32, uu2), Endian.Little);
216 writeInt(out[12..], @truncate(u32, uu3), Endian.Little);
217
218 ctx.secure_zero();
219 }
220};
208221
209test "poly1305 rfc7439 vector1" {222test "poly1305 rfc7439 vector1" {
210 const expected_mac = "\xa8\x06\x1d\xc1\x30\x51\x36\xc6\xc2\x2b\x8b\xaf\x0c\x01\x27\xa9";223 const expected_mac = "\xa8\x06\x1d\xc1\x30\x51\x36\xc6\xc2\x2b\x8b\xaf\x0c\x01\x27\xa9";
...@@ -214,7 +227,7 @@ test "poly1305 rfc7439 vector1" {...@@ -214,7 +227,7 @@ test "poly1305 rfc7439 vector1" {
214 "\x01\x03\x80\x8a\xfb\x0d\xb2\xfd\x4a\xbf\xf6\xaf\x41\x49\xf5\x1b";227 "\x01\x03\x80\x8a\xfb\x0d\xb2\xfd\x4a\xbf\xf6\xaf\x41\x49\xf5\x1b";
215228
216 var mac: [16]u8 = undefined;229 var mac: [16]u8 = undefined;
217 crypto_poly1305(mac[0..], msg, key);230 Poly1305.create(mac[0..], msg, key);
218231
219 std.debug.assert(std.mem.eql(u8, mac, expected_mac));232 std.debug.assert(std.mem.eql(u8, mac, expected_mac));
220}233}
std/crypto/sha1.zig+4-4
...@@ -26,8 +26,8 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam {...@@ -26,8 +26,8 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam {
2626
27pub const Sha1 = struct {27pub const Sha1 = struct {
28 const Self = this;28 const Self = this;
29 const block_size = 64;29 const block_length = 64;
30 const digest_size = 20;30 const digest_length = 20;
3131
32 s: [5]u32,32 s: [5]u32,
33 // Streaming Cache33 // Streaming Cache
...@@ -292,8 +292,8 @@ test "sha1 streaming" {...@@ -292,8 +292,8 @@ test "sha1 streaming" {
292}292}
293293
294test "sha1 aligned final" {294test "sha1 aligned final" {
295 var block = []u8{0} ** Sha1.block_size;295 var block = []u8{0} ** Sha1.block_length;
296 var out: [Sha1.digest_size]u8 = undefined;296 var out: [Sha1.digest_length]u8 = undefined;
297297
298 var h = Sha1.init();298 var h = Sha1.init();
299 h.update(block);299 h.update(block);
std/crypto/sha2.zig+8-8
...@@ -78,8 +78,8 @@ pub const Sha256 = Sha2_32(Sha256Params);...@@ -78,8 +78,8 @@ pub const Sha256 = Sha2_32(Sha256Params);
78fn Sha2_32(comptime params: Sha2Params32) type {78fn Sha2_32(comptime params: Sha2Params32) type {
79 return struct {79 return struct {
80 const Self = this;80 const Self = this;
81 const block_size = 64;81 const block_length = 64;
82 const digest_size = params.out_len / 8;82 const digest_length = params.out_len / 8;
8383
84 s: [8]u32,84 s: [8]u32,
85 // Streaming Cache85 // Streaming Cache
...@@ -338,8 +338,8 @@ test "sha256 streaming" {...@@ -338,8 +338,8 @@ test "sha256 streaming" {
338}338}
339339
340test "sha256 aligned final" {340test "sha256 aligned final" {
341 var block = []u8{0} ** Sha256.block_size;341 var block = []u8{0} ** Sha256.block_length;
342 var out: [Sha256.digest_size]u8 = undefined;342 var out: [Sha256.digest_length]u8 = undefined;
343343
344 var h = Sha256.init();344 var h = Sha256.init();
345 h.update(block);345 h.update(block);
...@@ -419,8 +419,8 @@ pub const Sha512 = Sha2_64(Sha512Params);...@@ -419,8 +419,8 @@ pub const Sha512 = Sha2_64(Sha512Params);
419fn Sha2_64(comptime params: Sha2Params64) type {419fn Sha2_64(comptime params: Sha2Params64) type {
420 return struct {420 return struct {
421 const Self = this;421 const Self = this;
422 const block_size = 128;422 const block_length = 128;
423 const digest_size = params.out_len / 8;423 const digest_length = params.out_len / 8;
424424
425 s: [8]u64,425 s: [8]u64,
426 // Streaming Cache426 // Streaming Cache
...@@ -715,8 +715,8 @@ test "sha512 streaming" {...@@ -715,8 +715,8 @@ test "sha512 streaming" {
715}715}
716716
717test "sha512 aligned final" {717test "sha512 aligned final" {
718 var block = []u8{0} ** Sha512.block_size;718 var block = []u8{0} ** Sha512.block_length;
719 var out: [Sha512.digest_size]u8 = undefined;719 var out: [Sha512.digest_length]u8 = undefined;
720720
721 var h = Sha512.init();721 var h = Sha512.init();
722 h.update(block);722 h.update(block);
std/crypto/sha3.zig+6-6
...@@ -13,8 +13,8 @@ pub const Sha3_512 = Keccak(512, 0x06);...@@ -13,8 +13,8 @@ pub const Sha3_512 = Keccak(512, 0x06);
13fn Keccak(comptime bits: usize, comptime delim: u8) type {13fn Keccak(comptime bits: usize, comptime delim: u8) type {
14 return struct {14 return struct {
15 const Self = this;15 const Self = this;
16 const block_size = 200;16 const block_length = 200;
17 const digest_size = bits / 8;17 const digest_length = bits / 8;
1818
19 s: [200]u8,19 s: [200]u8,
20 offset: usize,20 offset: usize,
...@@ -297,8 +297,8 @@ test "sha3-256 streaming" {...@@ -297,8 +297,8 @@ test "sha3-256 streaming" {
297}297}
298298
299test "sha3-256 aligned final" {299test "sha3-256 aligned final" {
300 var block = []u8{0} ** Sha3_256.block_size;300 var block = []u8{0} ** Sha3_256.block_length;
301 var out: [Sha3_256.digest_size]u8 = undefined;301 var out: [Sha3_256.digest_length]u8 = undefined;
302302
303 var h = Sha3_256.init();303 var h = Sha3_256.init();
304 h.update(block);304 h.update(block);
...@@ -368,8 +368,8 @@ test "sha3-512 streaming" {...@@ -368,8 +368,8 @@ test "sha3-512 streaming" {
368}368}
369369
370test "sha3-512 aligned final" {370test "sha3-512 aligned final" {
371 var block = []u8{0} ** Sha3_512.block_size;371 var block = []u8{0} ** Sha3_512.block_length;
372 var out: [Sha3_512.digest_size]u8 = undefined;372 var out: [Sha3_512.digest_length]u8 = undefined;
373373
374 var h = Sha3_512.init();374 var h = Sha3_512.init();
375 h.update(block);375 h.update(block);
std/crypto/x25519.zig+120-113
...@@ -9,6 +9,118 @@ const Endian = builtin.Endian;...@@ -9,6 +9,118 @@ const Endian = builtin.Endian;
9const readInt = std.mem.readInt;9const readInt = std.mem.readInt;
10const writeInt = std.mem.writeInt;10const writeInt = std.mem.writeInt;
1111
12// Based on Supercop's ref10 implementation.
13pub const X25519 = struct {
14 pub const secret_length = 32;
15 pub const minimum_key_length = 32;
16
17 fn trim_scalar(s: []u8) void {
18 s[0] &= 248;
19 s[31] &= 127;
20 s[31] |= 64;
21 }
22
23 fn scalar_bit(s: []const u8, i: usize) i32 {
24 return (s[i >> 3] >> @intCast(u3, i & 7)) & 1;
25 }
26
27 pub fn create(out: []u8, private_key: []const u8, public_key: []const u8) bool {
28 std.debug.assert(out.len >= secret_length);
29 std.debug.assert(private_key.len >= minimum_key_length);
30 std.debug.assert(public_key.len >= minimum_key_length);
31
32 var storage: [7]Fe = undefined;
33
34 var x1 = &storage[0];
35 var x2 = &storage[1];
36 var z2 = &storage[2];
37 var x3 = &storage[3];
38 var z3 = &storage[4];
39 var t0 = &storage[5];
40 var t1 = &storage[6];
41
42 // computes the scalar product
43 fe_frombytes(x1, public_key);
44
45 // restrict the possible scalar values
46 var e: [32]u8 = undefined;
47 for (e[0..]) |_, i| {
48 e[i] = private_key[i];
49 }
50 trim_scalar(e[0..]);
51
52 // computes the actual scalar product (the result is in x2 and z2)
53
54 // Montgomery ladder
55 // In projective coordinates, to avoid divisons: x = X / Z
56 // We don't care about the y coordinate, it's only 1 bit of information
57 fe_1(x2);
58 fe_0(z2); // "zero" point
59 fe_copy(x3, x1);
60 fe_1(z3);
61
62 var swap: i32 = 0;
63 var pos: isize = 254;
64 while (pos >= 0) : (pos -= 1) {
65 // constant time conditional swap before ladder step
66 const b = scalar_bit(e, @intCast(usize, pos));
67 swap ^= b; // xor trick avoids swapping at the end of the loop
68 fe_cswap(x2, x3, swap);
69 fe_cswap(z2, z3, swap);
70 swap = b; // anticipates one last swap after the loop
71
72 // Montgomery ladder step: replaces (P2, P3) by (P2*2, P2+P3)
73 // with differential addition
74 fe_sub(t0, x3, z3);
75 fe_sub(t1, x2, z2);
76 fe_add(x2, x2, z2);
77 fe_add(z2, x3, z3);
78 fe_mul(z3, t0, x2);
79 fe_mul(z2, z2, t1);
80 fe_sq(t0, t1);
81 fe_sq(t1, x2);
82 fe_add(x3, z3, z2);
83 fe_sub(z2, z3, z2);
84 fe_mul(x2, t1, t0);
85 fe_sub(t1, t1, t0);
86 fe_sq(z2, z2);
87 fe_mul121666(z3, t1);
88 fe_sq(x3, x3);
89 fe_add(t0, t0, z3);
90 fe_mul(z3, x1, z2);
91 fe_mul(z2, t1, t0);
92 }
93
94 // last swap is necessary to compensate for the xor trick
95 // Note: after this swap, P3 == P2 + P1.
96 fe_cswap(x2, x3, swap);
97 fe_cswap(z2, z3, swap);
98
99 // normalises the coordinates: x == X / Z
100 fe_invert(z2, z2);
101 fe_mul(x2, x2, z2);
102 fe_tobytes(out, x2);
103
104 x1.secure_zero();
105 x2.secure_zero();
106 x3.secure_zero();
107 t0.secure_zero();
108 t1.secure_zero();
109 z2.secure_zero();
110 z3.secure_zero();
111 std.mem.secureZero(u8, e[0..]);
112
113 // Returns false if the output is all zero
114 // (happens with some malicious public keys)
115 return !zerocmp(u8, out);
116 }
117
118 pub fn createPublicKey(public_key: []const u8, private_key: []const u8) bool {
119 var base_point = []u8{9} ++ []u8{0} ** 31;
120 return create(public_key, private_key, base_point);
121 }
122};
123
12// Constant time compare to zero.124// Constant time compare to zero.
13fn zerocmp(comptime T: type, a: []const T) bool {125fn zerocmp(comptime T: type, a: []const T) bool {
14 var s: T = 0;126 var s: T = 0;
...@@ -144,7 +256,9 @@ fn load24_le(s: []const u8) u32 {...@@ -144,7 +256,9 @@ fn load24_le(s: []const u8) u32 {
144 return s[0] | (u32(s[1]) << 8) | (u32(s[2]) << 16);256 return s[0] | (u32(s[1]) << 8) | (u32(s[2]) << 16);
145}257}
146258
147fn fe_frombytes(h: *Fe, s: [32]u8) void {259fn fe_frombytes(h: *Fe, s: []const u8) void {
260 std.debug.assert(s.len >= 32);
261
148 var t: [10]i64 = undefined;262 var t: [10]i64 = undefined;
149263
150 t[0] = readInt(s[0..4], u32, Endian.Little);264 t[0] = readInt(s[0..4], u32, Endian.Little);
...@@ -469,113 +583,6 @@ fn fe_isnonzero(f: *const Fe) bool {...@@ -469,113 +583,6 @@ fn fe_isnonzero(f: *const Fe) bool {
469 return isneg;583 return isneg;
470}584}
471585
472///////////////
473/// X-25519 /// Taken from Supercop's ref10 implementation.
474///////////////
475fn trim_scalar(s: []u8) void {
476 s[0] &= 248;
477 s[31] &= 127;
478 s[31] |= 64;
479}
480
481fn scalar_bit(s: []const u8, i: usize) i32 {
482 return (s[i >> 3] >> @intCast(u3, i & 7)) & 1;
483}
484
485pub fn crypto_x25519(raw_shared_secret: []u8, your_secret_key: [32]u8, their_public_key: [32]u8) bool {
486 std.debug.assert(raw_shared_secret.len >= 32);
487
488 var storage: [7]Fe = undefined;
489
490 var x1 = &storage[0];
491 var x2 = &storage[1];
492 var z2 = &storage[2];
493 var x3 = &storage[3];
494 var z3 = &storage[4];
495 var t0 = &storage[5];
496 var t1 = &storage[6];
497
498 // computes the scalar product
499 fe_frombytes(x1, their_public_key);
500
501 // restrict the possible scalar values
502 var e: [32]u8 = undefined;
503 for (e[0..]) |_, i| {
504 e[i] = your_secret_key[i];
505 }
506 trim_scalar(e[0..]);
507
508 // computes the actual scalar product (the result is in x2 and z2)
509
510 // Montgomery ladder
511 // In projective coordinates, to avoid divisons: x = X / Z
512 // We don't care about the y coordinate, it's only 1 bit of information
513 fe_1(x2);
514 fe_0(z2); // "zero" point
515 fe_copy(x3, x1);
516 fe_1(z3);
517
518 var swap: i32 = 0;
519 var pos: isize = 254;
520 while (pos >= 0) : (pos -= 1) {
521 // constant time conditional swap before ladder step
522 const b = scalar_bit(e, @intCast(usize, pos));
523 swap ^= b; // xor trick avoids swapping at the end of the loop
524 fe_cswap(x2, x3, swap);
525 fe_cswap(z2, z3, swap);
526 swap = b; // anticipates one last swap after the loop
527
528 // Montgomery ladder step: replaces (P2, P3) by (P2*2, P2+P3)
529 // with differential addition
530 fe_sub(t0, x3, z3);
531 fe_sub(t1, x2, z2);
532 fe_add(x2, x2, z2);
533 fe_add(z2, x3, z3);
534 fe_mul(z3, t0, x2);
535 fe_mul(z2, z2, t1);
536 fe_sq(t0, t1);
537 fe_sq(t1, x2);
538 fe_add(x3, z3, z2);
539 fe_sub(z2, z3, z2);
540 fe_mul(x2, t1, t0);
541 fe_sub(t1, t1, t0);
542 fe_sq(z2, z2);
543 fe_mul121666(z3, t1);
544 fe_sq(x3, x3);
545 fe_add(t0, t0, z3);
546 fe_mul(z3, x1, z2);
547 fe_mul(z2, t1, t0);
548 }
549
550 // last swap is necessary to compensate for the xor trick
551 // Note: after this swap, P3 == P2 + P1.
552 fe_cswap(x2, x3, swap);
553 fe_cswap(z2, z3, swap);
554
555 // normalises the coordinates: x == X / Z
556 fe_invert(z2, z2);
557 fe_mul(x2, x2, z2);
558 fe_tobytes(raw_shared_secret, x2);
559
560 x1.secure_zero();
561 x2.secure_zero();
562 x3.secure_zero();
563 t0.secure_zero();
564 t1.secure_zero();
565 z2.secure_zero();
566 z3.secure_zero();
567 std.mem.secureZero(u8, e[0..]);
568
569 // Returns false if the output is all zero
570 // (happens with some malicious public keys)
571 return !zerocmp(u8, raw_shared_secret);
572}
573
574pub fn crypto_x25519_public_key(public_key: []u8, secret_key: [32]u8) void {
575 var base_point = []u8{9} ++ []u8{0} ** 31;
576 crypto_x25519(public_key, secret_key, base_point);
577}
578
579test "x25519 rfc7748 vector1" {586test "x25519 rfc7748 vector1" {
580 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";587 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";
581 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";588 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";
...@@ -584,7 +591,7 @@ test "x25519 rfc7748 vector1" {...@@ -584,7 +591,7 @@ test "x25519 rfc7748 vector1" {
584591
585 var output: [32]u8 = undefined;592 var output: [32]u8 = undefined;
586593
587 std.debug.assert(crypto_x25519(output[0..], secret_key, public_key));594 std.debug.assert(X25519.create(output[0..], secret_key, public_key));
588 std.debug.assert(std.mem.eql(u8, output, expected_output));595 std.debug.assert(std.mem.eql(u8, output, expected_output));
589}596}
590597
...@@ -596,7 +603,7 @@ test "x25519 rfc7748 vector2" {...@@ -596,7 +603,7 @@ test "x25519 rfc7748 vector2" {
596603
597 var output: [32]u8 = undefined;604 var output: [32]u8 = undefined;
598605
599 std.debug.assert(crypto_x25519(output[0..], secret_key, public_key));606 std.debug.assert(X25519.create(output[0..], secret_key, public_key));
600 std.debug.assert(std.mem.eql(u8, output, expected_output));607 std.debug.assert(std.mem.eql(u8, output, expected_output));
601}608}
602609
...@@ -610,7 +617,7 @@ test "x25519 rfc7748 one iteration" {...@@ -610,7 +617,7 @@ test "x25519 rfc7748 one iteration" {
610 var i: usize = 0;617 var i: usize = 0;
611 while (i < 1) : (i += 1) {618 while (i < 1) : (i += 1) {
612 var output: [32]u8 = undefined;619 var output: [32]u8 = undefined;
613 std.debug.assert(crypto_x25519(output[0..], k, u));620 std.debug.assert(X25519.create(output[0..], k, u));
614621
615 std.mem.copy(u8, u[0..], k[0..]);622 std.mem.copy(u8, u[0..], k[0..]);
616 std.mem.copy(u8, k[0..], output[0..]);623 std.mem.copy(u8, k[0..], output[0..]);
...@@ -634,7 +641,7 @@ test "x25519 rfc7748 1,000 iterations" {...@@ -634,7 +641,7 @@ test "x25519 rfc7748 1,000 iterations" {
634 var i: usize = 0;641 var i: usize = 0;
635 while (i < 1000) : (i += 1) {642 while (i < 1000) : (i += 1) {
636 var output: [32]u8 = undefined;643 var output: [32]u8 = undefined;
637 std.debug.assert(crypto_x25519(output[0..], k, u));644 std.debug.assert(X25519.create(output[0..], k, u));
638645
639 std.mem.copy(u8, u[0..], k[0..]);646 std.mem.copy(u8, u[0..], k[0..]);
640 std.mem.copy(u8, k[0..], output[0..]);647 std.mem.copy(u8, k[0..], output[0..]);
...@@ -657,7 +664,7 @@ test "x25519 rfc7748 1,000,000 iterations" {...@@ -657,7 +664,7 @@ test "x25519 rfc7748 1,000,000 iterations" {
657 var i: usize = 0;664 var i: usize = 0;
658 while (i < 1000000) : (i += 1) {665 while (i < 1000000) : (i += 1) {
659 var output: [32]u8 = undefined;666 var output: [32]u8 = undefined;
660 std.debug.assert(crypto_x25519(output[0..], k, u));667 std.debug.assert(X25519.create(output[0..], k, u));
661668
662 std.mem.copy(u8, u[0..], k[0..]);669 std.mem.copy(u8, u[0..], k[0..]);
663 std.mem.copy(u8, k[0..], output[0..]);670 std.mem.copy(u8, k[0..], output[0..]);