authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-02 17:47:06+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-08-02 17:47:06+00:00
log35391f1709bb413e277ede1178d4714473561565
treed3f5b3ebbeaae76d930a11bd18bd978e9a7ddde4
parent6df35c5877c1a1060dcfd28d5d4092638e6e6754
parent1df33936d61c18c40653631d9625f982f8e54dd8
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #5968 from haliucinas/blake2

Blake2 improvements

1 files changed, 224 insertions(+), 27 deletions(-)

lib/std/crypto/blake2.zig+224-27
......@@ -1,8 +1,7 @@
11const mem = @import("../mem.zig");
2const math = @import("../math.zig");
3const endian = @import("../endian.zig");
4const debug = @import("../debug.zig");
52const builtin = @import("builtin");
3const debug = @import("../debug.zig");
4const math = @import("../math.zig");
65const htest = @import("test.zig");
76
87const RoundParam = struct {
......@@ -31,7 +30,7 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) RoundParam {
3130pub const Blake2s224 = Blake2s(224);
3231pub const Blake2s256 = Blake2s(256);
3332
34fn Blake2s(comptime out_len: usize) type {
33pub fn Blake2s(comptime out_len: usize) type {
3534 return struct {
3635 const Self = @This();
3736 pub const block_length = 64;
......@@ -67,10 +66,17 @@ fn Blake2s(comptime out_len: usize) type {
6766 buf: [64]u8,
6867 buf_len: u8,
6968
69 key: []const u8,
70
7071 pub fn init() Self {
72 return init_keyed("");
73 }
74
75 pub fn init_keyed(key: []const u8) Self {
7176 debug.assert(8 <= out_len and out_len <= 512);
7277
7378 var s: Self = undefined;
79 s.key = key;
7480 s.reset();
7581 return s;
7682 }
......@@ -78,14 +84,24 @@ fn Blake2s(comptime out_len: usize) type {
7884 pub fn reset(d: *Self) void {
7985 mem.copy(u32, d.h[0..], iv[0..]);
8086
81 // No key plus default parameters
82 d.h[0] ^= 0x01010000 ^ @intCast(u32, out_len >> 3);
87 // default parameters
88 d.h[0] ^= 0x01010000 ^ @truncate(u32, d.key.len << 8) ^ @intCast(u32, out_len >> 3);
8389 d.t = 0;
8490 d.buf_len = 0;
91
92 if (d.key.len > 0) {
93 mem.set(u8, d.buf[d.key.len..], 0);
94 d.update(d.key);
95 d.buf_len = 64;
96 }
8597 }
8698
8799 pub fn hash(b: []const u8, out: []u8) void {
88 var d = Self.init();
100 Self.hash_keyed("", b, out);
101 }
102
103 pub fn hash_keyed(key: []const u8, b: []const u8, out: []u8) void {
104 var d = Self.init_keyed(key);
89105 d.update(b);
90106 d.final(out);
91107 }
......@@ -94,7 +110,7 @@ fn Blake2s(comptime out_len: usize) type {
94110 var off: usize = 0;
95111
96112 // Partial buffer exists from previous update. Copy into buffer then hash.
97 if (d.buf_len != 0 and d.buf_len + b.len >= 64) {
113 if (d.buf_len != 0 and d.buf_len + b.len > 64) {
98114 off += 64 - d.buf_len;
99115 mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
100116 d.t += 64;
......@@ -103,7 +119,7 @@ fn Blake2s(comptime out_len: usize) type {
103119 }
104120
105121 // Full middle blocks.
106 while (off + 64 <= b.len) : (off += 64) {
122 while (off + 64 < b.len) : (off += 64) {
107123 d.t += 64;
108124 d.round(b[off .. off + 64], false);
109125 }
......@@ -123,7 +139,7 @@ fn Blake2s(comptime out_len: usize) type {
123139 const rr = d.h[0 .. out_len / 32];
124140
125141 for (rr) |s, j| {
126 mem.writeIntLittle(u32, out[4 * j ..][0..4], s);
142 mem.writeIntSliceLittle(u32, out[4 * j ..], s);
127143 }
128144 }
129145
......@@ -188,6 +204,9 @@ test "blake2s224 single" {
188204
189205 const h3 = "e4e5cb6c7cae41982b397bf7b7d2d9d1949823ae78435326e8db4912";
190206 htest.assertEqualHash(Blake2s224, h3, "The quick brown fox jumps over the lazy dog");
207
208 const h4 = "557381a78facd2b298640f4e32113e58967d61420af1aa939d0cfe01";
209 htest.assertEqualHash(Blake2s224, h4, "a" ** 32 ++ "b" ** 32);
191210}
192211
193212test "blake2s224 streaming" {
......@@ -212,6 +231,37 @@ test "blake2s224 streaming" {
212231 h.update("c");
213232 h.final(out[0..]);
214233 htest.assertEqual(h2, out[0..]);
234
235 const h3 = "557381a78facd2b298640f4e32113e58967d61420af1aa939d0cfe01";
236
237 h.reset();
238 h.update("a" ** 32);
239 h.update("b" ** 32);
240 h.final(out[0..]);
241 htest.assertEqual(h3, out[0..]);
242
243 h.reset();
244 h.update("a" ** 32 ++ "b" ** 32);
245 h.final(out[0..]);
246 htest.assertEqual(h3, out[0..]);
247}
248
249test "comptime blake2s224" {
250 comptime {
251 @setEvalBranchQuota(6000);
252 var block = [_]u8{0} ** Blake2s224.block_length;
253 var out: [Blake2s224.digest_length]u8 = undefined;
254
255 const h1 = "86b7611563293f8c73627df7a6d6ba25ca0548c2a6481f7d116ee576";
256
257 htest.assertEqualHash(Blake2s224, h1, block[0..]);
258
259 var h = Blake2s224.init();
260 h.update(&block);
261 h.final(out[0..]);
262
263 htest.assertEqual(h1, out[0..]);
264 }
215265}
216266
217267test "blake2s256 single" {
......@@ -223,6 +273,9 @@ test "blake2s256 single" {
223273
224274 const h3 = "606beeec743ccbeff6cbcdf5d5302aa855c256c29b88c8ed331ea1a6bf3c8812";
225275 htest.assertEqualHash(Blake2s256, h3, "The quick brown fox jumps over the lazy dog");
276
277 const h4 = "8d8711dade07a6b92b9a3ea1f40bee9b2c53ff3edd2a273dec170b0163568977";
278 htest.assertEqualHash(Blake2s256, h4, "a" ** 32 ++ "b" ** 32);
226279}
227280
228281test "blake2s256 streaming" {
......@@ -247,15 +300,60 @@ test "blake2s256 streaming" {
247300 h.update("c");
248301 h.final(out[0..]);
249302 htest.assertEqual(h2, out[0..]);
303
304 const h3 = "8d8711dade07a6b92b9a3ea1f40bee9b2c53ff3edd2a273dec170b0163568977";
305
306 h.reset();
307 h.update("a" ** 32);
308 h.update("b" ** 32);
309 h.final(out[0..]);
310 htest.assertEqual(h3, out[0..]);
311
312 h.reset();
313 h.update("a" ** 32 ++ "b" ** 32);
314 h.final(out[0..]);
315 htest.assertEqual(h3, out[0..]);
250316}
251317
252test "blake2s256 aligned final" {
253 var block = [_]u8{0} ** Blake2s256.block_length;
254 var out: [Blake2s256.digest_length]u8 = undefined;
318test "blake2s256 keyed" {
319 var out: [32]u8 = undefined;
320
321 const h1 = "10f918da4d74fab3302e48a5d67d03804b1ec95372a62a0f33b7c9fa28ba1ae6";
322 const key = "secret_key";
255323
256 var h = Blake2s256.init();
257 h.update(&block);
324 Blake2s256.hash_keyed(key, "a" ** 64 ++ "b" ** 64, &out);
325 htest.assertEqual(h1, out[0..]);
326
327 var h = Blake2s256.init_keyed(key);
328 h.update("a" ** 64 ++ "b" ** 64);
329 h.final(out[0..]);
330
331 htest.assertEqual(h1, out[0..]);
332
333 h.reset();
334 h.update("a" ** 64);
335 h.update("b" ** 64);
258336 h.final(out[0..]);
337
338 htest.assertEqual(h1, out[0..]);
339}
340
341test "comptime blake2s256" {
342 comptime {
343 @setEvalBranchQuota(6000);
344 var block = [_]u8{0} ** Blake2s256.block_length;
345 var out: [Blake2s256.digest_length]u8 = undefined;
346
347 const h1 = "ae09db7cd54f42b490ef09b6bc541af688e4959bb8c53f359a6f56e38ab454a3";
348
349 htest.assertEqualHash(Blake2s256, h1, block[0..]);
350
351 var h = Blake2s256.init();
352 h.update(&block);
353 h.final(out[0..]);
354
355 htest.assertEqual(h1, out[0..]);
356 }
259357}
260358
261359/////////////////////
......@@ -264,7 +362,7 @@ test "blake2s256 aligned final" {
264362pub const Blake2b384 = Blake2b(384);
265363pub const Blake2b512 = Blake2b(512);
266364
267fn Blake2b(comptime out_len: usize) type {
365pub fn Blake2b(comptime out_len: usize) type {
268366 return struct {
269367 const Self = @This();
270368 pub const block_length = 128;
......@@ -302,10 +400,17 @@ fn Blake2b(comptime out_len: usize) type {
302400 buf: [128]u8,
303401 buf_len: u8,
304402
403 key: []const u8,
404
305405 pub fn init() Self {
406 return init_keyed("");
407 }
408
409 pub fn init_keyed(key: []const u8) Self {
306410 debug.assert(8 <= out_len and out_len <= 512);
307411
308412 var s: Self = undefined;
413 s.key = key;
309414 s.reset();
310415 return s;
311416 }
......@@ -313,14 +418,24 @@ fn Blake2b(comptime out_len: usize) type {
313418 pub fn reset(d: *Self) void {
314419 mem.copy(u64, d.h[0..], iv[0..]);
315420
316 // No key plus default parameters
317 d.h[0] ^= 0x01010000 ^ (out_len >> 3);
421 // default parameters
422 d.h[0] ^= 0x01010000 ^ (d.key.len << 8) ^ (out_len >> 3);
318423 d.t = 0;
319424 d.buf_len = 0;
425
426 if (d.key.len > 0) {
427 mem.set(u8, d.buf[d.key.len..], 0);
428 d.update(d.key);
429 d.buf_len = 128;
430 }
320431 }
321432
322433 pub fn hash(b: []const u8, out: []u8) void {
323 var d = Self.init();
434 Self.hash_keyed("", b, out);
435 }
436
437 pub fn hash_keyed(key: []const u8, b: []const u8, out: []u8) void {
438 var d = Self.init_keyed(key);
324439 d.update(b);
325440 d.final(out);
326441 }
......@@ -329,7 +444,7 @@ fn Blake2b(comptime out_len: usize) type {
329444 var off: usize = 0;
330445
331446 // Partial buffer exists from previous update. Copy into buffer then hash.
332 if (d.buf_len != 0 and d.buf_len + b.len >= 128) {
447 if (d.buf_len != 0 and d.buf_len + b.len > 128) {
333448 off += 128 - d.buf_len;
334449 mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
335450 d.t += 128;
......@@ -338,7 +453,7 @@ fn Blake2b(comptime out_len: usize) type {
338453 }
339454
340455 // Full middle blocks.
341 while (off + 128 <= b.len) : (off += 128) {
456 while (off + 128 < b.len) : (off += 128) {
342457 d.t += 128;
343458 d.round(b[off .. off + 128], false);
344459 }
......@@ -356,7 +471,7 @@ fn Blake2b(comptime out_len: usize) type {
356471 const rr = d.h[0 .. out_len / 64];
357472
358473 for (rr) |s, j| {
359 mem.writeIntLittle(u64, out[8 * j ..][0..8], s);
474 mem.writeIntSliceLittle(u64, out[8 * j ..], s);
360475 }
361476 }
362477
......@@ -421,6 +536,9 @@ test "blake2b384 single" {
421536
422537 const h3 = "b7c81b228b6bd912930e8f0b5387989691c1cee1e65aade4da3b86a3c9f678fc8018f6ed9e2906720c8d2a3aeda9c03d";
423538 htest.assertEqualHash(Blake2b384, h3, "The quick brown fox jumps over the lazy dog");
539
540 const h4 = "b7283f0172fecbbd7eca32ce10d8a6c06b453cb3cf675b33eb4246f0da2bb94a6c0bdd6eec0b5fd71ec4fd51be80bf4c";
541 htest.assertEqualHash(Blake2b384, h4, "a" ** 64 ++ "b" ** 64);
424542}
425543
426544test "blake2b384 streaming" {
......@@ -445,6 +563,37 @@ test "blake2b384 streaming" {
445563 h.update("c");
446564 h.final(out[0..]);
447565 htest.assertEqual(h2, out[0..]);
566
567 const h3 = "b7283f0172fecbbd7eca32ce10d8a6c06b453cb3cf675b33eb4246f0da2bb94a6c0bdd6eec0b5fd71ec4fd51be80bf4c";
568
569 h.reset();
570 h.update("a" ** 64 ++ "b" ** 64);
571 h.final(out[0..]);
572 htest.assertEqual(h3, out[0..]);
573
574 h.reset();
575 h.update("a" ** 64);
576 h.update("b" ** 64);
577 h.final(out[0..]);
578 htest.assertEqual(h3, out[0..]);
579}
580
581test "comptime blake2b384" {
582 comptime {
583 @setEvalBranchQuota(7000);
584 var block = [_]u8{0} ** Blake2b384.block_length;
585 var out: [Blake2b384.digest_length]u8 = undefined;
586
587 const h1 = "e8aa1931ea0422e4446fecdd25c16cf35c240b10cb4659dd5c776eddcaa4d922397a589404b46eb2e53d78132d05fd7d";
588
589 htest.assertEqualHash(Blake2b384, h1, block[0..]);
590
591 var h = Blake2b384.init();
592 h.update(&block);
593 h.final(out[0..]);
594
595 htest.assertEqual(h1, out[0..]);
596 }
448597}
449598
450599test "blake2b512 single" {
......@@ -456,6 +605,9 @@ test "blake2b512 single" {
456605
457606 const h3 = "a8add4bdddfd93e4877d2746e62817b116364a1fa7bc148d95090bc7333b3673f82401cf7aa2e4cb1ecd90296e3f14cb5413f8ed77be73045b13914cdcd6a918";
458607 htest.assertEqualHash(Blake2b512, h3, "The quick brown fox jumps over the lazy dog");
608
609 const h4 = "049980af04d6a2cf16b4b49793c3ed7e40732073788806f2c989ebe9547bda0541d63abe298ec8955d08af48ae731f2e8a0bd6d201655a5473b4aa79d211b920";
610 htest.assertEqualHash(Blake2b512, h4, "a" ** 64 ++ "b" ** 64);
459611}
460612
461613test "blake2b512 streaming" {
......@@ -480,13 +632,58 @@ test "blake2b512 streaming" {
480632 h.update("c");
481633 h.final(out[0..]);
482634 htest.assertEqual(h2, out[0..]);
635
636 const h3 = "049980af04d6a2cf16b4b49793c3ed7e40732073788806f2c989ebe9547bda0541d63abe298ec8955d08af48ae731f2e8a0bd6d201655a5473b4aa79d211b920";
637
638 h.reset();
639 h.update("a" ** 64 ++ "b" ** 64);
640 h.final(out[0..]);
641 htest.assertEqual(h3, out[0..]);
642
643 h.reset();
644 h.update("a" ** 64);
645 h.update("b" ** 64);
646 h.final(out[0..]);
647 htest.assertEqual(h3, out[0..]);
483648}
484649
485test "blake2b512 aligned final" {
486 var block = [_]u8{0} ** Blake2b512.block_length;
487 var out: [Blake2b512.digest_length]u8 = undefined;
650test "blake2b512 keyed" {
651 var out: [64]u8 = undefined;
488652
489 var h = Blake2b512.init();
490 h.update(&block);
653 const h1 = "8a978060ccaf582f388f37454363071ac9a67e3a704585fd879fb8a419a447e389c7c6de790faa20a7a7dccf197de736bc5b40b98a930b36df5bee7555750c4d";
654 const key = "secret_key";
655
656 Blake2b512.hash_keyed(key, "a" ** 64 ++ "b" ** 64, &out);
657 htest.assertEqual(h1, out[0..]);
658
659 var h = Blake2b512.init_keyed(key);
660 h.update("a" ** 64 ++ "b" ** 64);
661 h.final(out[0..]);
662
663 htest.assertEqual(h1, out[0..]);
664
665 h.reset();
666 h.update("a" ** 64);
667 h.update("b" ** 64);
491668 h.final(out[0..]);
669
670 htest.assertEqual(h1, out[0..]);
671}
672
673test "comptime blake2b512" {
674 comptime {
675 @setEvalBranchQuota(8000);
676 var block = [_]u8{0} ** Blake2b512.block_length;
677 var out: [Blake2b512.digest_length]u8 = undefined;
678
679 const h1 = "865939e120e6805438478841afb739ae4250cf372653078a065cdcfffca4caf798e6d462b65d658fc165782640eded70963449ae1500fb0f24981d7727e22c41";
680
681 htest.assertEqualHash(Blake2b512, h1, block[0..]);
682
683 var h = Blake2b512.init();
684 h.update(&block);
685 h.final(out[0..]);
686
687 htest.assertEqual(h1, out[0..]);
688 }
492689}