| ... | ... | @@ -1,8 +1,7 @@ |
| 1 | 1 | const mem = @import("../mem.zig"); |
| 2 | | const math = @import("../math.zig"); |
| 3 | | const endian = @import("../endian.zig"); |
| 4 | | const debug = @import("../debug.zig"); |
| 5 | 2 | const builtin = @import("builtin"); |
| 3 | const debug = @import("../debug.zig"); |
| 4 | const math = @import("../math.zig"); |
| 6 | 5 | const htest = @import("test.zig"); |
| 7 | 6 | |
| 8 | 7 | const RoundParam = struct { |
| ... | ... | @@ -31,7 +30,7 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) RoundParam { |
| 31 | 30 | pub const Blake2s224 = Blake2s(224); |
| 32 | 31 | pub const Blake2s256 = Blake2s(256); |
| 33 | 32 | |
| 34 | | fn Blake2s(comptime out_len: usize) type { |
| 33 | pub fn Blake2s(comptime out_len: usize) type { |
| 35 | 34 | return struct { |
| 36 | 35 | const Self = @This(); |
| 37 | 36 | pub const block_length = 64; |
| ... | ... | @@ -67,10 +66,17 @@ fn Blake2s(comptime out_len: usize) type { |
| 67 | 66 | buf: [64]u8, |
| 68 | 67 | buf_len: u8, |
| 69 | 68 | |
| 69 | key: []const u8, |
| 70 | |
| 70 | 71 | pub fn init() Self { |
| 72 | return init_keyed(""); |
| 73 | } |
| 74 | |
| 75 | pub fn init_keyed(key: []const u8) Self { |
| 71 | 76 | debug.assert(8 <= out_len and out_len <= 512); |
| 72 | 77 | |
| 73 | 78 | var s: Self = undefined; |
| 79 | s.key = key; |
| 74 | 80 | s.reset(); |
| 75 | 81 | return s; |
| 76 | 82 | } |
| ... | ... | @@ -78,14 +84,24 @@ fn Blake2s(comptime out_len: usize) type { |
| 78 | 84 | pub fn reset(d: *Self) void { |
| 79 | 85 | mem.copy(u32, d.h[0..], iv[0..]); |
| 80 | 86 | |
| 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); |
| 83 | 89 | d.t = 0; |
| 84 | 90 | 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 | } |
| 85 | 97 | } |
| 86 | 98 | |
| 87 | 99 | 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); |
| 89 | 105 | d.update(b); |
| 90 | 106 | d.final(out); |
| 91 | 107 | } |
| ... | ... | @@ -94,7 +110,7 @@ fn Blake2s(comptime out_len: usize) type { |
| 94 | 110 | var off: usize = 0; |
| 95 | 111 | |
| 96 | 112 | // 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) { |
| 98 | 114 | off += 64 - d.buf_len; |
| 99 | 115 | mem.copy(u8, d.buf[d.buf_len..], b[0..off]); |
| 100 | 116 | d.t += 64; |
| ... | ... | @@ -103,7 +119,7 @@ fn Blake2s(comptime out_len: usize) type { |
| 103 | 119 | } |
| 104 | 120 | |
| 105 | 121 | // Full middle blocks. |
| 106 | | while (off + 64 <= b.len) : (off += 64) { |
| 122 | while (off + 64 < b.len) : (off += 64) { |
| 107 | 123 | d.t += 64; |
| 108 | 124 | d.round(b[off .. off + 64], false); |
| 109 | 125 | } |
| ... | ... | @@ -123,7 +139,7 @@ fn Blake2s(comptime out_len: usize) type { |
| 123 | 139 | const rr = d.h[0 .. out_len / 32]; |
| 124 | 140 | |
| 125 | 141 | for (rr) |s, j| { |
| 126 | | mem.writeIntLittle(u32, out[4 * j ..][0..4], s); |
| 142 | mem.writeIntSliceLittle(u32, out[4 * j ..], s); |
| 127 | 143 | } |
| 128 | 144 | } |
| 129 | 145 | |
| ... | ... | @@ -188,6 +204,9 @@ test "blake2s224 single" { |
| 188 | 204 | |
| 189 | 205 | const h3 = "e4e5cb6c7cae41982b397bf7b7d2d9d1949823ae78435326e8db4912"; |
| 190 | 206 | 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); |
| 191 | 210 | } |
| 192 | 211 | |
| 193 | 212 | test "blake2s224 streaming" { |
| ... | ... | @@ -212,6 +231,37 @@ test "blake2s224 streaming" { |
| 212 | 231 | h.update("c"); |
| 213 | 232 | h.final(out[0..]); |
| 214 | 233 | 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 | |
| 249 | test "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 | } |
| 215 | 265 | } |
| 216 | 266 | |
| 217 | 267 | test "blake2s256 single" { |
| ... | ... | @@ -223,6 +273,9 @@ test "blake2s256 single" { |
| 223 | 273 | |
| 224 | 274 | const h3 = "606beeec743ccbeff6cbcdf5d5302aa855c256c29b88c8ed331ea1a6bf3c8812"; |
| 225 | 275 | 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); |
| 226 | 279 | } |
| 227 | 280 | |
| 228 | 281 | test "blake2s256 streaming" { |
| ... | ... | @@ -247,15 +300,60 @@ test "blake2s256 streaming" { |
| 247 | 300 | h.update("c"); |
| 248 | 301 | h.final(out[0..]); |
| 249 | 302 | 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..]); |
| 250 | 316 | } |
| 251 | 317 | |
| 252 | | test "blake2s256 aligned final" { |
| 253 | | var block = [_]u8{0} ** Blake2s256.block_length; |
| 254 | | var out: [Blake2s256.digest_length]u8 = undefined; |
| 318 | test "blake2s256 keyed" { |
| 319 | var out: [32]u8 = undefined; |
| 320 | |
| 321 | const h1 = "10f918da4d74fab3302e48a5d67d03804b1ec95372a62a0f33b7c9fa28ba1ae6"; |
| 322 | const key = "secret_key"; |
| 255 | 323 | |
| 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); |
| 258 | 336 | h.final(out[0..]); |
| 337 | |
| 338 | htest.assertEqual(h1, out[0..]); |
| 339 | } |
| 340 | |
| 341 | test "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 | } |
| 259 | 357 | } |
| 260 | 358 | |
| 261 | 359 | ///////////////////// |
| ... | ... | @@ -264,7 +362,7 @@ test "blake2s256 aligned final" { |
| 264 | 362 | pub const Blake2b384 = Blake2b(384); |
| 265 | 363 | pub const Blake2b512 = Blake2b(512); |
| 266 | 364 | |
| 267 | | fn Blake2b(comptime out_len: usize) type { |
| 365 | pub fn Blake2b(comptime out_len: usize) type { |
| 268 | 366 | return struct { |
| 269 | 367 | const Self = @This(); |
| 270 | 368 | pub const block_length = 128; |
| ... | ... | @@ -302,10 +400,17 @@ fn Blake2b(comptime out_len: usize) type { |
| 302 | 400 | buf: [128]u8, |
| 303 | 401 | buf_len: u8, |
| 304 | 402 | |
| 403 | key: []const u8, |
| 404 | |
| 305 | 405 | pub fn init() Self { |
| 406 | return init_keyed(""); |
| 407 | } |
| 408 | |
| 409 | pub fn init_keyed(key: []const u8) Self { |
| 306 | 410 | debug.assert(8 <= out_len and out_len <= 512); |
| 307 | 411 | |
| 308 | 412 | var s: Self = undefined; |
| 413 | s.key = key; |
| 309 | 414 | s.reset(); |
| 310 | 415 | return s; |
| 311 | 416 | } |
| ... | ... | @@ -313,14 +418,24 @@ fn Blake2b(comptime out_len: usize) type { |
| 313 | 418 | pub fn reset(d: *Self) void { |
| 314 | 419 | mem.copy(u64, d.h[0..], iv[0..]); |
| 315 | 420 | |
| 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); |
| 318 | 423 | d.t = 0; |
| 319 | 424 | 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 | } |
| 320 | 431 | } |
| 321 | 432 | |
| 322 | 433 | 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); |
| 324 | 439 | d.update(b); |
| 325 | 440 | d.final(out); |
| 326 | 441 | } |
| ... | ... | @@ -329,7 +444,7 @@ fn Blake2b(comptime out_len: usize) type { |
| 329 | 444 | var off: usize = 0; |
| 330 | 445 | |
| 331 | 446 | // 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) { |
| 333 | 448 | off += 128 - d.buf_len; |
| 334 | 449 | mem.copy(u8, d.buf[d.buf_len..], b[0..off]); |
| 335 | 450 | d.t += 128; |
| ... | ... | @@ -338,7 +453,7 @@ fn Blake2b(comptime out_len: usize) type { |
| 338 | 453 | } |
| 339 | 454 | |
| 340 | 455 | // Full middle blocks. |
| 341 | | while (off + 128 <= b.len) : (off += 128) { |
| 456 | while (off + 128 < b.len) : (off += 128) { |
| 342 | 457 | d.t += 128; |
| 343 | 458 | d.round(b[off .. off + 128], false); |
| 344 | 459 | } |
| ... | ... | @@ -356,7 +471,7 @@ fn Blake2b(comptime out_len: usize) type { |
| 356 | 471 | const rr = d.h[0 .. out_len / 64]; |
| 357 | 472 | |
| 358 | 473 | for (rr) |s, j| { |
| 359 | | mem.writeIntLittle(u64, out[8 * j ..][0..8], s); |
| 474 | mem.writeIntSliceLittle(u64, out[8 * j ..], s); |
| 360 | 475 | } |
| 361 | 476 | } |
| 362 | 477 | |
| ... | ... | @@ -421,6 +536,9 @@ test "blake2b384 single" { |
| 421 | 536 | |
| 422 | 537 | const h3 = "b7c81b228b6bd912930e8f0b5387989691c1cee1e65aade4da3b86a3c9f678fc8018f6ed9e2906720c8d2a3aeda9c03d"; |
| 423 | 538 | 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); |
| 424 | 542 | } |
| 425 | 543 | |
| 426 | 544 | test "blake2b384 streaming" { |
| ... | ... | @@ -445,6 +563,37 @@ test "blake2b384 streaming" { |
| 445 | 563 | h.update("c"); |
| 446 | 564 | h.final(out[0..]); |
| 447 | 565 | 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 | |
| 581 | test "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 | } |
| 448 | 597 | } |
| 449 | 598 | |
| 450 | 599 | test "blake2b512 single" { |
| ... | ... | @@ -456,6 +605,9 @@ test "blake2b512 single" { |
| 456 | 605 | |
| 457 | 606 | const h3 = "a8add4bdddfd93e4877d2746e62817b116364a1fa7bc148d95090bc7333b3673f82401cf7aa2e4cb1ecd90296e3f14cb5413f8ed77be73045b13914cdcd6a918"; |
| 458 | 607 | 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); |
| 459 | 611 | } |
| 460 | 612 | |
| 461 | 613 | test "blake2b512 streaming" { |
| ... | ... | @@ -480,13 +632,58 @@ test "blake2b512 streaming" { |
| 480 | 632 | h.update("c"); |
| 481 | 633 | h.final(out[0..]); |
| 482 | 634 | 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..]); |
| 483 | 648 | } |
| 484 | 649 | |
| 485 | | test "blake2b512 aligned final" { |
| 486 | | var block = [_]u8{0} ** Blake2b512.block_length; |
| 487 | | var out: [Blake2b512.digest_length]u8 = undefined; |
| 650 | test "blake2b512 keyed" { |
| 651 | var out: [64]u8 = undefined; |
| 488 | 652 | |
| 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); |
| 491 | 668 | h.final(out[0..]); |
| 669 | |
| 670 | htest.assertEqual(h1, out[0..]); |
| 671 | } |
| 672 | |
| 673 | test "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 | } |
| 492 | 689 | } |