diff options
| author | Andrea Orru <andrea@orru.io> | 2018-08-06 01:43:19 -0400 |
|---|---|---|
| committer | Andrea Orru <andrea@orru.io> | 2018-08-06 01:43:19 -0400 |
| commit | d2f5e57b68da0b16e5789ca19045ccbcb4ecfa8d (patch) | |
| tree | e9fa3caec533a0d1e2b434868b2fde1f9240e5c8 /std/crypto | |
| parent | 06614b3fa09954464c2e2f32756cacedc178a282 (diff) | |
| parent | 63a23e848a62d5f167f8d5478de9766cb24aa6eb (diff) | |
| download | zig-d2f5e57b68da0b16e5789ca19045ccbcb4ecfa8d.tar.gz zig-d2f5e57b68da0b16e5789ca19045ccbcb4ecfa8d.zip | |
Merge branch 'master' into zen_stdlib
Diffstat (limited to 'std/crypto')
| -rw-r--r-- | std/crypto/blake2.zig | 507 | ||||
| -rw-r--r-- | std/crypto/hmac.zig | 4 | ||||
| -rw-r--r-- | std/crypto/md5.zig | 154 | ||||
| -rw-r--r-- | std/crypto/sha1.zig | 104 | ||||
| -rw-r--r-- | std/crypto/sha2.zig | 861 | ||||
| -rw-r--r-- | std/crypto/sha3.zig | 281 | ||||
| -rw-r--r-- | std/crypto/test.zig | 3 | ||||
| -rw-r--r-- | std/crypto/throughput_test.zig | 29 |
8 files changed, 1049 insertions, 894 deletions
diff --git a/std/crypto/blake2.zig b/std/crypto/blake2.zig index 99f0e629cd..947133e4cf 100644 --- a/std/crypto/blake2.zig +++ b/std/crypto/blake2.zig @@ -6,11 +6,23 @@ const builtin = @import("builtin"); const htest = @import("test.zig"); const RoundParam = struct { - a: usize, b: usize, c: usize, d: usize, x: usize, y: usize, + a: usize, + b: usize, + c: usize, + d: usize, + x: usize, + y: usize, }; fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) RoundParam { - return RoundParam { .a = a, .b = b, .c = c, .d = d, .x = x, .y = y, }; + return RoundParam{ + .a = a, + .b = b, + .c = c, + .d = d, + .x = x, + .y = y, + }; } ///////////////////// @@ -19,145 +31,153 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) RoundParam { pub const Blake2s224 = Blake2s(224); pub const Blake2s256 = Blake2s(256); -fn Blake2s(comptime out_len: usize) type { return struct { - const Self = this; - const block_size = 64; - const digest_size = out_len / 8; +fn Blake2s(comptime out_len: usize) type { + return struct { + const Self = this; + const block_size = 64; + const digest_size = out_len / 8; + + const iv = [8]u32{ + 0x6A09E667, + 0xBB67AE85, + 0x3C6EF372, + 0xA54FF53A, + 0x510E527F, + 0x9B05688C, + 0x1F83D9AB, + 0x5BE0CD19, + }; - const iv = [8]u32 { - 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, - 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19, - }; + const sigma = [10][16]u8{ + []const u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + []const u8{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, + []const u8{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, + []const u8{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, + []const u8{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, + []const u8{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, + []const u8{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, + []const u8{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, + []const u8{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, + []const u8{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, + }; - const sigma = [10][16]u8 { - []const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, - []const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, - []const u8 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, - []const u8 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, - []const u8 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, - []const u8 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, - []const u8 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, - []const u8 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, - []const u8 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, - []const u8 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, - }; + h: [8]u32, + t: u64, + // Streaming cache + buf: [64]u8, + buf_len: u8, - h: [8]u32, - t: u64, - // Streaming cache - buf: [64]u8, - buf_len: u8, - - pub fn init() Self { - debug.assert(8 <= out_len and out_len <= 512); - - var s: Self = undefined; - s.reset(); - return s; - } - - pub fn reset(d: &Self) void { - mem.copy(u32, d.h[0..], iv[0..]); - - // No key plus default parameters - d.h[0] ^= 0x01010000 ^ u32(out_len >> 3); - d.t = 0; - d.buf_len = 0; - } - - pub fn hash(b: []const u8, out: []u8) void { - var d = Self.init(); - d.update(b); - d.final(out); - } - - pub fn update(d: &Self, b: []const u8) void { - var off: usize = 0; - - // Partial buffer exists from previous update. Copy into buffer then hash. - if (d.buf_len != 0 and d.buf_len + b.len > 64) { - off += 64 - d.buf_len; - mem.copy(u8, d.buf[d.buf_len..], b[0..off]); - d.t += 64; - d.round(d.buf[0..], false); - d.buf_len = 0; + pub fn init() Self { + debug.assert(8 <= out_len and out_len <= 512); + + var s: Self = undefined; + s.reset(); + return s; } - // Full middle blocks. - while (off + 64 <= b.len) : (off += 64) { - d.t += 64; - d.round(b[off..off + 64], false); + pub fn reset(d: *Self) void { + mem.copy(u32, d.h[0..], iv[0..]); + + // No key plus default parameters + d.h[0] ^= 0x01010000 ^ @intCast(u32, out_len >> 3); + d.t = 0; + d.buf_len = 0; } - // Copy any remainder for next pass. - mem.copy(u8, d.buf[d.buf_len..], b[off..]); - d.buf_len += u8(b[off..].len); - } + pub fn hash(b: []const u8, out: []u8) void { + var d = Self.init(); + d.update(b); + d.final(out); + } - pub fn final(d: &Self, out: []u8) void { - debug.assert(out.len >= out_len / 8); + pub fn update(d: *Self, b: []const u8) void { + var off: usize = 0; - mem.set(u8, d.buf[d.buf_len..], 0); - d.t += d.buf_len; - d.round(d.buf[0..], true); + // Partial buffer exists from previous update. Copy into buffer then hash. + if (d.buf_len != 0 and d.buf_len + b.len > 64) { + off += 64 - d.buf_len; + mem.copy(u8, d.buf[d.buf_len..], b[0..off]); + d.t += 64; + d.round(d.buf[0..], false); + d.buf_len = 0; + } - const rr = d.h[0 .. out_len / 32]; + // Full middle blocks. + while (off + 64 <= b.len) : (off += 64) { + d.t += 64; + d.round(b[off .. off + 64], false); + } - for (rr) |s, j| { - mem.writeInt(out[4*j .. 4*j + 4], s, builtin.Endian.Little); + // Copy any remainder for next pass. + mem.copy(u8, d.buf[d.buf_len..], b[off..]); + d.buf_len += @intCast(u8, b[off..].len); } - } - fn round(d: &Self, b: []const u8, last: bool) void { - debug.assert(b.len == 64); + pub fn final(d: *Self, out: []u8) void { + debug.assert(out.len >= out_len / 8); - var m: [16]u32 = undefined; - var v: [16]u32 = undefined; + mem.set(u8, d.buf[d.buf_len..], 0); + d.t += d.buf_len; + d.round(d.buf[0..], true); - for (m) |*r, i| { - *r = mem.readIntLE(u32, b[4*i .. 4*i + 4]); - } + const rr = d.h[0 .. out_len / 32]; - var k: usize = 0; - while (k < 8) : (k += 1) { - v[k] = d.h[k]; - v[k+8] = iv[k]; + for (rr) |s, j| { + mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little); + } } - v[12] ^= @truncate(u32, d.t); - v[13] ^= u32(d.t >> 32); - if (last) v[14] = ~v[14]; - - const rounds = comptime []RoundParam { - Rp(0, 4, 8, 12, 0, 1), - Rp(1, 5, 9, 13, 2, 3), - Rp(2, 6, 10, 14, 4, 5), - Rp(3, 7, 11, 15, 6, 7), - Rp(0, 5, 10, 15, 8, 9), - Rp(1, 6, 11, 12, 10, 11), - Rp(2, 7, 8, 13, 12, 13), - Rp(3, 4, 9, 14, 14, 15), - }; + fn round(d: *Self, b: []const u8, last: bool) void { + debug.assert(b.len == 64); - comptime var j: usize = 0; - inline while (j < 10) : (j += 1) { - inline for (rounds) |r| { - v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]]; - v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(16)); - v[r.c] = v[r.c] +% v[r.d]; - v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(12)); - v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]]; - v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(8)); - v[r.c] = v[r.c] +% v[r.d]; - v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(7)); + var m: [16]u32 = undefined; + var v: [16]u32 = undefined; + + for (m) |*r, i| { + r.* = mem.readIntLE(u32, b[4 * i .. 4 * i + 4]); } - } - for (d.h) |*r, i| { - *r ^= v[i] ^ v[i + 8]; + var k: usize = 0; + while (k < 8) : (k += 1) { + v[k] = d.h[k]; + v[k + 8] = iv[k]; + } + + v[12] ^= @truncate(u32, d.t); + v[13] ^= @intCast(u32, d.t >> 32); + if (last) v[14] = ~v[14]; + + const rounds = comptime []RoundParam{ + Rp(0, 4, 8, 12, 0, 1), + Rp(1, 5, 9, 13, 2, 3), + Rp(2, 6, 10, 14, 4, 5), + Rp(3, 7, 11, 15, 6, 7), + Rp(0, 5, 10, 15, 8, 9), + Rp(1, 6, 11, 12, 10, 11), + Rp(2, 7, 8, 13, 12, 13), + Rp(3, 4, 9, 14, 14, 15), + }; + + comptime var j: usize = 0; + inline while (j < 10) : (j += 1) { + inline for (rounds) |r| { + v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]]; + v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(16)); + v[r.c] = v[r.c] +% v[r.d]; + v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(12)); + v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]]; + v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(8)); + v[r.c] = v[r.c] +% v[r.d]; + v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(7)); + } + } + + for (d.h) |*r, i| { + r.* ^= v[i] ^ v[i + 8]; + } } - } -};} + }; +} test "blake2s224 single" { const h1 = "1fa1291e65248b37b3433475b2a0dd63d54a11ecc4e3e034e7bc1ef4"; @@ -230,7 +250,7 @@ test "blake2s256 streaming" { } test "blake2s256 aligned final" { - var block = []u8 {0} ** Blake2s256.block_size; + var block = []u8{0} ** Blake2s256.block_size; var out: [Blake2s256.digest_size]u8 = undefined; var h = Blake2s256.init(); @@ -238,154 +258,159 @@ test "blake2s256 aligned final" { h.final(out[0..]); } - ///////////////////// // Blake2b pub const Blake2b384 = Blake2b(384); pub const Blake2b512 = Blake2b(512); -fn Blake2b(comptime out_len: usize) type { return struct { - const Self = this; - const block_size = 128; - const digest_size = out_len / 8; +fn Blake2b(comptime out_len: usize) type { + return struct { + const Self = this; + const block_size = 128; + const digest_size = out_len / 8; + + const iv = [8]u64{ + 0x6a09e667f3bcc908, + 0xbb67ae8584caa73b, + 0x3c6ef372fe94f82b, + 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, + 0x9b05688c2b3e6c1f, + 0x1f83d9abfb41bd6b, + 0x5be0cd19137e2179, + }; - const iv = [8]u64 { - 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, - 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, - 0x510e527fade682d1, 0x9b05688c2b3e6c1f, - 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, - }; + const sigma = [12][16]u8{ + []const u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + []const u8{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, + []const u8{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, + []const u8{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, + []const u8{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, + []const u8{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, + []const u8{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, + []const u8{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, + []const u8{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, + []const u8{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, + []const u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + []const u8{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, + }; - const sigma = [12][16]u8 { - []const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, - []const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, - []const u8 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, - []const u8 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, - []const u8 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, - []const u8 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, - []const u8 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, - []const u8 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, - []const u8 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, - []const u8 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 }, - []const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, - []const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, - }; + h: [8]u64, + t: u128, + // Streaming cache + buf: [128]u8, + buf_len: u8, - h: [8]u64, - t: u128, - // Streaming cache - buf: [128]u8, - buf_len: u8, - - pub fn init() Self { - debug.assert(8 <= out_len and out_len <= 512); - - var s: Self = undefined; - s.reset(); - return s; - } - - pub fn reset(d: &Self) void { - mem.copy(u64, d.h[0..], iv[0..]); - - // No key plus default parameters - d.h[0] ^= 0x01010000 ^ (out_len >> 3); - d.t = 0; - d.buf_len = 0; - } - - pub fn hash(b: []const u8, out: []u8) void { - var d = Self.init(); - d.update(b); - d.final(out); - } - - pub fn update(d: &Self, b: []const u8) void { - var off: usize = 0; - - // Partial buffer exists from previous update. Copy into buffer then hash. - if (d.buf_len != 0 and d.buf_len + b.len > 128) { - off += 128 - d.buf_len; - mem.copy(u8, d.buf[d.buf_len..], b[0..off]); - d.t += 128; - d.round(d.buf[0..], false); + pub fn init() Self { + debug.assert(8 <= out_len and out_len <= 512); + + var s: Self = undefined; + s.reset(); + return s; + } + + pub fn reset(d: *Self) void { + mem.copy(u64, d.h[0..], iv[0..]); + + // No key plus default parameters + d.h[0] ^= 0x01010000 ^ (out_len >> 3); + d.t = 0; d.buf_len = 0; } - // Full middle blocks. - while (off + 128 <= b.len) : (off += 128) { - d.t += 128; - d.round(b[off..off + 128], false); + pub fn hash(b: []const u8, out: []u8) void { + var d = Self.init(); + d.update(b); + d.final(out); } - // Copy any remainder for next pass. - mem.copy(u8, d.buf[d.buf_len..], b[off..]); - d.buf_len += u8(b[off..].len); - } + pub fn update(d: *Self, b: []const u8) void { + var off: usize = 0; - pub fn final(d: &Self, out: []u8) void { - mem.set(u8, d.buf[d.buf_len..], 0); - d.t += d.buf_len; - d.round(d.buf[0..], true); + // Partial buffer exists from previous update. Copy into buffer then hash. + if (d.buf_len != 0 and d.buf_len + b.len > 128) { + off += 128 - d.buf_len; + mem.copy(u8, d.buf[d.buf_len..], b[0..off]); + d.t += 128; + d.round(d.buf[0..], false); + d.buf_len = 0; + } - const rr = d.h[0 .. out_len / 64]; + // Full middle blocks. + while (off + 128 <= b.len) : (off += 128) { + d.t += 128; + d.round(b[off .. off + 128], false); + } - for (rr) |s, j| { - mem.writeInt(out[8*j .. 8*j + 8], s, builtin.Endian.Little); + // Copy any remainder for next pass. + mem.copy(u8, d.buf[d.buf_len..], b[off..]); + d.buf_len += @intCast(u8, b[off..].len); } - } - fn round(d: &Self, b: []const u8, last: bool) void { - debug.assert(b.len == 128); + pub fn final(d: *Self, out: []u8) void { + mem.set(u8, d.buf[d.buf_len..], 0); + d.t += d.buf_len; + d.round(d.buf[0..], true); - var m: [16]u64 = undefined; - var v: [16]u64 = undefined; + const rr = d.h[0 .. out_len / 64]; - for (m) |*r, i| { - *r = mem.readIntLE(u64, b[8*i .. 8*i + 8]); + for (rr) |s, j| { + mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Little); + } } - var k: usize = 0; - while (k < 8) : (k += 1) { - v[k] = d.h[k]; - v[k+8] = iv[k]; - } + fn round(d: *Self, b: []const u8, last: bool) void { + debug.assert(b.len == 128); - v[12] ^= @truncate(u64, d.t); - v[13] ^= u64(d.t >> 64); - if (last) v[14] = ~v[14]; - - const rounds = comptime []RoundParam { - Rp(0, 4, 8, 12, 0, 1), - Rp(1, 5, 9, 13, 2, 3), - Rp(2, 6, 10, 14, 4, 5), - Rp(3, 7, 11, 15, 6, 7), - Rp(0, 5, 10, 15, 8, 9), - Rp(1, 6, 11, 12, 10, 11), - Rp(2, 7, 8, 13, 12, 13), - Rp(3, 4, 9, 14, 14, 15), - }; + var m: [16]u64 = undefined; + var v: [16]u64 = undefined; - comptime var j: usize = 0; - inline while (j < 12) : (j += 1) { - inline for (rounds) |r| { - v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]]; - v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(32)); - v[r.c] = v[r.c] +% v[r.d]; - v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(24)); - v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]]; - v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(16)); - v[r.c] = v[r.c] +% v[r.d]; - v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(63)); + for (m) |*r, i| { + r.* = mem.readIntLE(u64, b[8 * i .. 8 * i + 8]); + } + + var k: usize = 0; + while (k < 8) : (k += 1) { + v[k] = d.h[k]; + v[k + 8] = iv[k]; } - } - for (d.h) |*r, i| { - *r ^= v[i] ^ v[i + 8]; + v[12] ^= @truncate(u64, d.t); + v[13] ^= @intCast(u64, d.t >> 64); + if (last) v[14] = ~v[14]; + + const rounds = comptime []RoundParam{ + Rp(0, 4, 8, 12, 0, 1), + Rp(1, 5, 9, 13, 2, 3), + Rp(2, 6, 10, 14, 4, 5), + Rp(3, 7, 11, 15, 6, 7), + Rp(0, 5, 10, 15, 8, 9), + Rp(1, 6, 11, 12, 10, 11), + Rp(2, 7, 8, 13, 12, 13), + Rp(3, 4, 9, 14, 14, 15), + }; + + comptime var j: usize = 0; + inline while (j < 12) : (j += 1) { + inline for (rounds) |r| { + v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]]; + v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(32)); + v[r.c] = v[r.c] +% v[r.d]; + v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(24)); + v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]]; + v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(16)); + v[r.c] = v[r.c] +% v[r.d]; + v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(63)); + } + } + + for (d.h) |*r, i| { + r.* ^= v[i] ^ v[i + 8]; + } } - } -};} + }; +} test "blake2b384 single" { const h1 = "b32811423377f52d7862286ee1a72ee540524380fda1724a6f25d7978c6fd3244a6caf0498812673c5e05ef583825100"; @@ -458,7 +483,7 @@ test "blake2b512 streaming" { } test "blake2b512 aligned final" { - var block = []u8 {0} ** Blake2b512.block_size; + var block = []u8{0} ** Blake2b512.block_size; var out: [Blake2b512.digest_size]u8 = undefined; var h = Blake2b512.init(); diff --git a/std/crypto/hmac.zig b/std/crypto/hmac.zig index 2a36f15b71..1415e88cf4 100644 --- a/std/crypto/hmac.zig +++ b/std/crypto/hmac.zig @@ -29,12 +29,12 @@ pub fn Hmac(comptime H: type) type { var o_key_pad: [H.block_size]u8 = undefined; for (o_key_pad) |*b, i| { - *b = scratch[i] ^ 0x5c; + b.* = scratch[i] ^ 0x5c; } var i_key_pad: [H.block_size]u8 = undefined; for (i_key_pad) |*b, i| { - *b = scratch[i] ^ 0x36; + b.* = scratch[i] ^ 0x36; } // HMAC(k, m) = H(o_key_pad | H(i_key_pad | message)) where | is concatenation diff --git a/std/crypto/md5.zig b/std/crypto/md5.zig index 705b2428a7..23fe2313a0 100644 --- a/std/crypto/md5.zig +++ b/std/crypto/md5.zig @@ -6,12 +6,25 @@ const debug = @import("../debug/index.zig"); const fmt = @import("../fmt/index.zig"); const RoundParam = struct { - a: usize, b: usize, c: usize, d: usize, - k: usize, s: u32, t: u32 + a: usize, + b: usize, + c: usize, + d: usize, + k: usize, + s: u32, + t: u32, }; fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundParam { - return RoundParam { .a = a, .b = b, .c = c, .d = d, .k = k, .s = s, .t = t }; + return RoundParam{ + .a = a, + .b = b, + .c = c, + .d = d, + .k = k, + .s = s, + .t = t, + }; } pub const Md5 = struct { @@ -31,7 +44,7 @@ pub const Md5 = struct { return d; } - pub fn reset(d: &Self) void { + pub fn reset(d: *Self) void { d.s[0] = 0x67452301; d.s[1] = 0xEFCDAB89; d.s[2] = 0x98BADCFE; @@ -46,7 +59,7 @@ pub const Md5 = struct { d.final(out); } - pub fn update(d: &Self, b: []const u8) void { + pub fn update(d: *Self, b: []const u8) void { var off: usize = 0; // Partial buffer exists from previous update. Copy into buffer then hash. @@ -60,18 +73,18 @@ pub const Md5 = struct { // Full middle blocks. while (off + 64 <= b.len) : (off += 64) { - d.round(b[off..off + 64]); + d.round(b[off .. off + 64]); } // Copy any remainder for next pass. mem.copy(u8, d.buf[d.buf_len..], b[off..]); - d.buf_len += u8(b[off..].len); + d.buf_len += @intCast(u8, b[off..].len); // Md5 uses the bottom 64-bits for length padding d.total_len +%= b.len; } - pub fn final(d: &Self, out: []u8) void { + pub fn final(d: *Self, out: []u8) void { debug.assert(out.len >= 16); // The buffer here will never be completely full. @@ -90,20 +103,20 @@ pub const Md5 = struct { // Append message length. var i: usize = 1; var len = d.total_len >> 5; - d.buf[56] = u8(d.total_len & 0x1f) << 3; + d.buf[56] = @intCast(u8, d.total_len & 0x1f) << 3; while (i < 8) : (i += 1) { - d.buf[56 + i] = u8(len & 0xff); + d.buf[56 + i] = @intCast(u8, len & 0xff); len >>= 8; } d.round(d.buf[0..]); for (d.s) |s, j| { - mem.writeInt(out[4*j .. 4*j + 4], s, builtin.Endian.Little); + mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little); } } - fn round(d: &Self, b: []const u8) void { + fn round(d: *Self, b: []const u8) void { debug.assert(b.len == 64); var s: [16]u32 = undefined; @@ -112,30 +125,33 @@ pub const Md5 = struct { while (i < 16) : (i += 1) { // NOTE: Performing or's separately improves perf by ~10% s[i] = 0; - s[i] |= u32(b[i*4+0]); - s[i] |= u32(b[i*4+1]) << 8; - s[i] |= u32(b[i*4+2]) << 16; - s[i] |= u32(b[i*4+3]) << 24; + s[i] |= u32(b[i * 4 + 0]); + s[i] |= u32(b[i * 4 + 1]) << 8; + s[i] |= u32(b[i * 4 + 2]) << 16; + s[i] |= u32(b[i * 4 + 3]) << 24; } - var v: [4]u32 = []u32 { - d.s[0], d.s[1], d.s[2], d.s[3], + var v: [4]u32 = []u32{ + d.s[0], + d.s[1], + d.s[2], + d.s[3], }; - const round0 = comptime []RoundParam { - Rp(0, 1, 2, 3, 0, 7, 0xD76AA478), - Rp(3, 0, 1, 2, 1, 12, 0xE8C7B756), - Rp(2, 3, 0, 1, 2, 17, 0x242070DB), - Rp(1, 2, 3, 0, 3, 22, 0xC1BDCEEE), - Rp(0, 1, 2, 3, 4, 7, 0xF57C0FAF), - Rp(3, 0, 1, 2, 5, 12, 0x4787C62A), - Rp(2, 3, 0, 1, 6, 17, 0xA8304613), - Rp(1, 2, 3, 0, 7, 22, 0xFD469501), - Rp(0, 1, 2, 3, 8, 7, 0x698098D8), - Rp(3, 0, 1, 2, 9, 12, 0x8B44F7AF), + const round0 = comptime []RoundParam{ + Rp(0, 1, 2, 3, 0, 7, 0xD76AA478), + Rp(3, 0, 1, 2, 1, 12, 0xE8C7B756), + Rp(2, 3, 0, 1, 2, 17, 0x242070DB), + Rp(1, 2, 3, 0, 3, 22, 0xC1BDCEEE), + Rp(0, 1, 2, 3, 4, 7, 0xF57C0FAF), + Rp(3, 0, 1, 2, 5, 12, 0x4787C62A), + Rp(2, 3, 0, 1, 6, 17, 0xA8304613), + Rp(1, 2, 3, 0, 7, 22, 0xFD469501), + Rp(0, 1, 2, 3, 8, 7, 0x698098D8), + Rp(3, 0, 1, 2, 9, 12, 0x8B44F7AF), Rp(2, 3, 0, 1, 10, 17, 0xFFFF5BB1), Rp(1, 2, 3, 0, 11, 22, 0x895CD7BE), - Rp(0, 1, 2, 3, 12, 7, 0x6B901122), + Rp(0, 1, 2, 3, 12, 7, 0x6B901122), Rp(3, 0, 1, 2, 13, 12, 0xFD987193), Rp(2, 3, 0, 1, 14, 17, 0xA679438E), Rp(1, 2, 3, 0, 15, 22, 0x49B40821), @@ -145,22 +161,22 @@ pub const Md5 = struct { v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s); } - const round1 = comptime []RoundParam { - Rp(0, 1, 2, 3, 1, 5, 0xF61E2562), - Rp(3, 0, 1, 2, 6, 9, 0xC040B340), + const round1 = comptime []RoundParam{ + Rp(0, 1, 2, 3, 1, 5, 0xF61E2562), + Rp(3, 0, 1, 2, 6, 9, 0xC040B340), Rp(2, 3, 0, 1, 11, 14, 0x265E5A51), - Rp(1, 2, 3, 0, 0, 20, 0xE9B6C7AA), - Rp(0, 1, 2, 3, 5, 5, 0xD62F105D), - Rp(3, 0, 1, 2, 10, 9, 0x02441453), + Rp(1, 2, 3, 0, 0, 20, 0xE9B6C7AA), + Rp(0, 1, 2, 3, 5, 5, 0xD62F105D), + Rp(3, 0, 1, 2, 10, 9, 0x02441453), Rp(2, 3, 0, 1, 15, 14, 0xD8A1E681), - Rp(1, 2, 3, 0, 4, 20, 0xE7D3FBC8), - Rp(0, 1, 2, 3, 9, 5, 0x21E1CDE6), - Rp(3, 0, 1, 2, 14, 9, 0xC33707D6), - Rp(2, 3, 0, 1, 3, 14, 0xF4D50D87), - Rp(1, 2, 3, 0, 8, 20, 0x455A14ED), - Rp(0, 1, 2, 3, 13, 5, 0xA9E3E905), - Rp(3, 0, 1, 2, 2, 9, 0xFCEFA3F8), - Rp(2, 3, 0, 1, 7, 14, 0x676F02D9), + Rp(1, 2, 3, 0, 4, 20, 0xE7D3FBC8), + Rp(0, 1, 2, 3, 9, 5, 0x21E1CDE6), + Rp(3, 0, 1, 2, 14, 9, 0xC33707D6), + Rp(2, 3, 0, 1, 3, 14, 0xF4D50D87), + Rp(1, 2, 3, 0, 8, 20, 0x455A14ED), + Rp(0, 1, 2, 3, 13, 5, 0xA9E3E905), + Rp(3, 0, 1, 2, 2, 9, 0xFCEFA3F8), + Rp(2, 3, 0, 1, 7, 14, 0x676F02D9), Rp(1, 2, 3, 0, 12, 20, 0x8D2A4C8A), }; inline for (round1) |r| { @@ -168,46 +184,46 @@ pub const Md5 = struct { v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s); } - const round2 = comptime []RoundParam { - Rp(0, 1, 2, 3, 5, 4, 0xFFFA3942), - Rp(3, 0, 1, 2, 8, 11, 0x8771F681), + const round2 = comptime []RoundParam{ + Rp(0, 1, 2, 3, 5, 4, 0xFFFA3942), + Rp(3, 0, 1, 2, 8, 11, 0x8771F681), Rp(2, 3, 0, 1, 11, 16, 0x6D9D6122), Rp(1, 2, 3, 0, 14, 23, 0xFDE5380C), - Rp(0, 1, 2, 3, 1, 4, 0xA4BEEA44), - Rp(3, 0, 1, 2, 4, 11, 0x4BDECFA9), - Rp(2, 3, 0, 1, 7, 16, 0xF6BB4B60), + Rp(0, 1, 2, 3, 1, 4, 0xA4BEEA44), + Rp(3, 0, 1, 2, 4, 11, 0x4BDECFA9), + Rp(2, 3, 0, 1, 7, 16, 0xF6BB4B60), Rp(1, 2, 3, 0, 10, 23, 0xBEBFBC70), - Rp(0, 1, 2, 3, 13, 4, 0x289B7EC6), - Rp(3, 0, 1, 2, 0, 11, 0xEAA127FA), - Rp(2, 3, 0, 1, 3, 16, 0xD4EF3085), - Rp(1, 2, 3, 0, 6, 23, 0x04881D05), - Rp(0, 1, 2, 3, 9, 4, 0xD9D4D039), + Rp(0, 1, 2, 3, 13, 4, 0x289B7EC6), + Rp(3, 0, 1, 2, 0, 11, 0xEAA127FA), + Rp(2, 3, 0, 1, 3, 16, 0xD4EF3085), + Rp(1, 2, 3, 0, 6, 23, 0x04881D05), + Rp(0, 1, 2, 3, 9, 4, 0xD9D4D039), Rp(3, 0, 1, 2, 12, 11, 0xE6DB99E5), Rp(2, 3, 0, 1, 15, 16, 0x1FA27CF8), - Rp(1, 2, 3, 0, 2, 23, 0xC4AC5665), + Rp(1, 2, 3, 0, 2, 23, 0xC4AC5665), }; inline for (round2) |r| { v[r.a] = v[r.a] +% (v[r.b] ^ v[r.c] ^ v[r.d]) +% r.t +% s[r.k]; v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s); } - const round3 = comptime []RoundParam { - Rp(0, 1, 2, 3, 0, 6, 0xF4292244), - Rp(3, 0, 1, 2, 7, 10, 0x432AFF97), + const round3 = comptime []RoundParam{ + Rp(0, 1, 2, 3, 0, 6, 0xF4292244), + Rp(3, 0, 1, 2, 7, 10, 0x432AFF97), Rp(2, 3, 0, 1, 14, 15, 0xAB9423A7), - Rp(1, 2, 3, 0, 5, 21, 0xFC93A039), - Rp(0, 1, 2, 3, 12, 6, 0x655B59C3), - Rp(3, 0, 1, 2, 3, 10, 0x8F0CCC92), + Rp(1, 2, 3, 0, 5, 21, 0xFC93A039), + Rp(0, 1, 2, 3, 12, 6, 0x655B59C3), + Rp(3, 0, 1, 2, 3, 10, 0x8F0CCC92), Rp(2, 3, 0, 1, 10, 15, 0xFFEFF47D), - Rp(1, 2, 3, 0, 1, 21, 0x85845DD1), - Rp(0, 1, 2, 3, 8, 6, 0x6FA87E4F), + Rp(1, 2, 3, 0, 1, 21, 0x85845DD1), + Rp(0, 1, 2, 3, 8, 6, 0x6FA87E4F), Rp(3, 0, 1, 2, 15, 10, 0xFE2CE6E0), - Rp(2, 3, 0, 1, 6, 15, 0xA3014314), + Rp(2, 3, 0, 1, 6, 15, 0xA3014314), Rp(1, 2, 3, 0, 13, 21, 0x4E0811A1), - Rp(0, 1, 2, 3, 4, 6, 0xF7537E82), + Rp(0, 1, 2, 3, 4, 6, 0xF7537E82), Rp(3, 0, 1, 2, 11, 10, 0xBD3AF235), - Rp(2, 3, 0, 1, 2, 15, 0x2AD7D2BB), - Rp(1, 2, 3, 0, 9, 21, 0xEB86D391), + Rp(2, 3, 0, 1, 2, 15, 0x2AD7D2BB), + Rp(1, 2, 3, 0, 9, 21, 0xEB86D391), }; inline for (round3) |r| { v[r.a] = v[r.a] +% (v[r.c] ^ (v[r.b] | ~v[r.d])) +% r.t +% s[r.k]; @@ -255,7 +271,7 @@ test "md5 streaming" { } test "md5 aligned final" { - var block = []u8 {0} ** Md5.block_size; + var block = []u8{0} ** Md5.block_size; var out: [Md5.digest_size]u8 = undefined; var h = Md5.init(); diff --git a/std/crypto/sha1.zig b/std/crypto/sha1.zig index 333597b12d..451cfb3122 100644 --- a/std/crypto/sha1.zig +++ b/std/crypto/sha1.zig @@ -4,14 +4,24 @@ const endian = @import("../endian.zig"); const debug = @import("../debug/index.zig"); const builtin = @import("builtin"); -pub const u160 = @IntType(false, 160); - const RoundParam = struct { - a: usize, b: usize, c: usize, d: usize, e: usize, i: u32, + a: usize, + b: usize, + c: usize, + d: usize, + e: usize, + i: u32, }; fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam { - return RoundParam { .a = a, .b = b, .c = c, .d = d, .e = e, .i = i }; + return RoundParam{ + .a = a, + .b = b, + .c = c, + .d = d, + .e = e, + .i = i, + }; } pub const Sha1 = struct { @@ -31,7 +41,7 @@ pub const Sha1 = struct { return d; } - pub fn reset(d: &Self) void { + pub fn reset(d: *Self) void { d.s[0] = 0x67452301; d.s[1] = 0xEFCDAB89; d.s[2] = 0x98BADCFE; @@ -47,7 +57,7 @@ pub const Sha1 = struct { d.final(out); } - pub fn update(d: &Self, b: []const u8) void { + pub fn update(d: *Self, b: []const u8) void { var off: usize = 0; // Partial buffer exists from previous update. Copy into buffer then hash. @@ -61,17 +71,17 @@ pub const Sha1 = struct { // Full middle blocks. while (off + 64 <= b.len) : (off += 64) { - d.round(b[off..off + 64]); + d.round(b[off .. off + 64]); } // Copy any remainder for next pass. mem.copy(u8, d.buf[d.buf_len..], b[off..]); - d.buf_len += u8(b[off..].len); + d.buf_len += @intCast(u8, b[off..].len); d.total_len += b.len; } - pub fn final(d: &Self, out: []u8) void { + pub fn final(d: *Self, out: []u8) void { debug.assert(out.len >= 20); // The buffer here will never be completely full. @@ -90,39 +100,43 @@ pub const Sha1 = struct { // Append message length. var i: usize = 1; var len = d.total_len >> 5; - d.buf[63] = u8(d.total_len & 0x1f) << 3; + d.buf[63] = @intCast(u8, d.total_len & 0x1f) << 3; while (i < 8) : (i += 1) { - d.buf[63 - i] = u8(len & 0xff); + d.buf[63 - i] = @intCast(u8, len & 0xff); len >>= 8; } d.round(d.buf[0..]); for (d.s) |s, j| { - mem.writeInt(out[4*j .. 4*j + 4], s, builtin.Endian.Big); + mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big); } } - fn round(d: &Self, b: []const u8) void { + fn round(d: *Self, b: []const u8) void { debug.assert(b.len == 64); var s: [16]u32 = undefined; - var v: [5]u32 = []u32 { - d.s[0], d.s[1], d.s[2], d.s[3], d.s[4], + var v: [5]u32 = []u32{ + d.s[0], + d.s[1], + d.s[2], + d.s[3], + d.s[4], }; - const round0a = comptime []RoundParam { - Rp(0, 1, 2, 3, 4, 0), - Rp(4, 0, 1, 2, 3, 1), - Rp(3, 4, 0, 1, 2, 2), - Rp(2, 3, 4, 0, 1, 3), - Rp(1, 2, 3, 4, 0, 4), - Rp(0, 1, 2, 3, 4, 5), - Rp(4, 0, 1, 2, 3, 6), - Rp(3, 4, 0, 1, 2, 7), - Rp(2, 3, 4, 0, 1, 8), - Rp(1, 2, 3, 4, 0, 9), + const round0a = comptime []RoundParam{ + Rp(0, 1, 2, 3, 4, 0), + Rp(4, 0, 1, 2, 3, 1), + Rp(3, 4, 0, 1, 2, 2), + Rp(2, 3, 4, 0, 1, 3), + Rp(1, 2, 3, 4, 0, 4), + Rp(0, 1, 2, 3, 4, 5), + Rp(4, 0, 1, 2, 3, 6), + Rp(3, 4, 0, 1, 2, 7), + Rp(2, 3, 4, 0, 1, 8), + Rp(1, 2, 3, 4, 0, 9), Rp(0, 1, 2, 3, 4, 10), Rp(4, 0, 1, 2, 3, 11), Rp(3, 4, 0, 1, 2, 12), @@ -131,32 +145,27 @@ pub const Sha1 = struct { Rp(0, 1, 2, 3, 4, 15), }; inline for (round0a) |r| { - s[r.i] = (u32(b[r.i * 4 + 0]) << 24) | - (u32(b[r.i * 4 + 1]) << 16) | - (u32(b[r.i * 4 + 2]) << 8) | - (u32(b[r.i * 4 + 3]) << 0); + s[r.i] = (u32(b[r.i * 4 + 0]) << 24) | (u32(b[r.i * 4 + 1]) << 16) | (u32(b[r.i * 4 + 2]) << 8) | (u32(b[r.i * 4 + 3]) << 0); - v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x5A827999 +% s[r.i & 0xf] - +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d])); + v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x5A827999 +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d])); v[r.b] = math.rotl(u32, v[r.b], u32(30)); } - const round0b = comptime []RoundParam { + const round0b = comptime []RoundParam{ Rp(4, 0, 1, 2, 3, 16), Rp(3, 4, 0, 1, 2, 17), Rp(2, 3, 4, 0, 1, 18), Rp(1, 2, 3, 4, 0, 19), }; inline for (round0b) |r| { - const t = s[(r.i-3) & 0xf] ^ s[(r.i-8) & 0xf] ^ s[(r.i-14) & 0xf] ^ s[(r.i-16) & 0xf]; + const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf]; s[r.i & 0xf] = math.rotl(u32, t, u32(1)); - v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x5A827999 +% s[r.i & 0xf] - +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d])); + v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x5A827999 +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d])); v[r.b] = math.rotl(u32, v[r.b], u32(30)); } - const round1 = comptime []RoundParam { + const round1 = comptime []RoundParam{ Rp(0, 1, 2, 3, 4, 20), Rp(4, 0, 1, 2, 3, 21), Rp(3, 4, 0, 1, 2, 22), @@ -179,15 +188,14 @@ pub const Sha1 = struct { Rp(1, 2, 3, 4, 0, 39), }; inline for (round1) |r| { - const t = s[(r.i-3) & 0xf] ^ s[(r.i-8) & 0xf] ^ s[(r.i-14) & 0xf] ^ s[(r.i-16) & 0xf]; + const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf]; s[r.i & 0xf] = math.rotl(u32, t, u32(1)); - v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x6ED9EBA1 +% s[r.i & 0xf] - +% (v[r.b] ^ v[r.c] ^ v[r.d]); + v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x6ED9EBA1 +% s[r.i & 0xf] +% (v[r.b] ^ v[r.c] ^ v[r.d]); v[r.b] = math.rotl(u32, v[r.b], u32(30)); } - const round2 = comptime []RoundParam { + const round2 = comptime []RoundParam{ Rp(0, 1, 2, 3, 4, 40), Rp(4, 0, 1, 2, 3, 41), Rp(3, 4, 0, 1, 2, 42), @@ -210,15 +218,14 @@ pub const Sha1 = struct { Rp(1, 2, 3, 4, 0, 59), }; inline for (round2) |r| { - const t = s[(r.i-3) & 0xf] ^ s[(r.i-8) & 0xf] ^ s[(r.i-14) & 0xf] ^ s[(r.i-16) & 0xf]; + const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf]; s[r.i & 0xf] = math.rotl(u32, t, u32(1)); - v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x8F1BBCDC +% s[r.i & 0xf] - +% ((v[r.b] & v[r.c]) ^ (v[r.b] & v[r.d]) ^ (v[r.c] & v[r.d])); + v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x8F1BBCDC +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) ^ (v[r.b] & v[r.d]) ^ (v[r.c] & v[r.d])); v[r.b] = math.rotl(u32, v[r.b], u32(30)); } - const round3 = comptime []RoundParam { + const round3 = comptime []RoundParam{ Rp(0, 1, 2, 3, 4, 60), Rp(4, 0, 1, 2, 3, 61), Rp(3, 4, 0, 1, 2, 62), @@ -241,11 +248,10 @@ pub const Sha1 = struct { Rp(1, 2, 3, 4, 0, 79), }; inline for (round3) |r| { - const t = s[(r.i-3) & 0xf] ^ s[(r.i-8) & 0xf] ^ s[(r.i-14) & 0xf] ^ s[(r.i-16) & 0xf]; + const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf]; s[r.i & 0xf] = math.rotl(u32, t, u32(1)); - v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0xCA62C1D6 +% s[r.i & 0xf] - +% (v[r.b] ^ v[r.c] ^ v[r.d]); + v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0xCA62C1D6 +% s[r.i & 0xf] +% (v[r.b] ^ v[r.c] ^ v[r.d]); v[r.b] = math.rotl(u32, v[r.b], u32(30)); } @@ -286,7 +292,7 @@ test "sha1 streaming" { } test "sha1 aligned final" { - var block = []u8 {0} ** Sha1.block_size; + var block = []u8{0} ** Sha1.block_size; var out: [Sha1.digest_size]u8 = undefined; var h = Sha1.init(); diff --git a/std/crypto/sha2.zig b/std/crypto/sha2.zig index b70450c0ad..d1b915835c 100644 --- a/std/crypto/sha2.zig +++ b/std/crypto/sha2.zig @@ -9,12 +9,31 @@ const htest = @import("test.zig"); // Sha224 + Sha256 const RoundParam256 = struct { - a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, - i: usize, k: u32, + a: usize, + b: usize, + c: usize, + d: usize, + e: usize, + f: usize, + g: usize, + h: usize, + i: usize, + k: u32, }; fn Rp256(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u32) RoundParam256 { - return RoundParam256 { .a = a, .b = b, .c = c, .d = d, .e = e, .f = f, .g = g, .h = h, .i = i, .k = k }; + return RoundParam256{ + .a = a, + .b = b, + .c = c, + .d = d, + .e = e, + .f = f, + .g = g, + .h = h, + .i = i, + .k = k, + }; } const Sha2Params32 = struct { @@ -29,7 +48,7 @@ const Sha2Params32 = struct { out_len: usize, }; -const Sha224Params = Sha2Params32 { +const Sha224Params = Sha2Params32{ .iv0 = 0xC1059ED8, .iv1 = 0x367CD507, .iv2 = 0x3070DD17, @@ -41,7 +60,7 @@ const Sha224Params = Sha2Params32 { .out_len = 224, }; -const Sha256Params = Sha2Params32 { +const Sha256Params = Sha2Params32{ .iv0 = 0x6A09E667, .iv1 = 0xBB67AE85, .iv2 = 0x3C6EF372, @@ -56,216 +75,215 @@ const Sha256Params = Sha2Params32 { pub const Sha224 = Sha2_32(Sha224Params); pub const Sha256 = Sha2_32(Sha256Params); -fn Sha2_32(comptime params: Sha2Params32) type { return struct { - const Self = this; - const block_size = 64; - const digest_size = params.out_len / 8; - - s: [8]u32, - // Streaming Cache - buf: [64]u8, - buf_len: u8, - total_len: u64, - - pub fn init() Self { - var d: Self = undefined; - d.reset(); - return d; - } - - pub fn reset(d: &Self) void { - d.s[0] = params.iv0; - d.s[1] = params.iv1; - d.s[2] = params.iv2; - d.s[3] = params.iv3; - d.s[4] = params.iv4; - d.s[5] = params.iv5; - d.s[6] = params.iv6; - d.s[7] = params.iv7; - d.buf_len = 0; - d.total_len = 0; - } - - pub fn hash(b: []const u8, out: []u8) void { - var d = Self.init(); - d.update(b); - d.final(out); - } - - pub fn update(d: &Self, b: []const u8) void { - var off: usize = 0; - - // Partial buffer exists from previous update. Copy into buffer then hash. - if (d.buf_len != 0 and d.buf_len + b.len > 64) { - off += 64 - d.buf_len; - mem.copy(u8, d.buf[d.buf_len..], b[0..off]); +fn Sha2_32(comptime params: Sha2Params32) type { + return struct { + const Self = this; + const block_size = 64; + const digest_size = params.out_len / 8; + + s: [8]u32, + // Streaming Cache + buf: [64]u8, + buf_len: u8, + total_len: u64, + + pub fn init() Self { + var d: Self = undefined; + d.reset(); + return d; + } - d.round(d.buf[0..]); + pub fn reset(d: *Self) void { + d.s[0] = params.iv0; + d.s[1] = params.iv1; + d.s[2] = params.iv2; + d.s[3] = params.iv3; + d.s[4] = params.iv4; + d.s[5] = params.iv5; + d.s[6] = params.iv6; + d.s[7] = params.iv7; d.buf_len = 0; + d.total_len = 0; } - // Full middle blocks. - while (off + 64 <= b.len) : (off += 64) { - d.round(b[off..off + 64]); + pub fn hash(b: []const u8, out: []u8) void { + var d = Self.init(); + d.update(b); + d.final(out); } - // Copy any remainder for next pass. - mem.copy(u8, d.buf[d.buf_len..], b[off..]); - d.buf_len += u8(b[off..].len); + pub fn update(d: *Self, b: []const u8) void { + var off: usize = 0; - d.total_len += b.len; - } + // Partial buffer exists from previous update. Copy into buffer then hash. + if (d.buf_len != 0 and d.buf_len + b.len > 64) { + off += 64 - d.buf_len; + mem.copy(u8, d.buf[d.buf_len..], b[0..off]); - pub fn final(d: &Self, out: []u8) void { - debug.assert(out.len >= params.out_len / 8); + d.round(d.buf[0..]); + d.buf_len = 0; + } - // The buffer here will never be completely full. - mem.set(u8, d.buf[d.buf_len..], 0); + // Full middle blocks. + while (off + 64 <= b.len) : (off += 64) { + d.round(b[off .. off + 64]); + } - // Append padding bits. - d.buf[d.buf_len] = 0x80; - d.buf_len += 1; + // Copy any remainder for next pass. + mem.copy(u8, d.buf[d.buf_len..], b[off..]); + d.buf_len += @intCast(u8, b[off..].len); - // > 448 mod 512 so need to add an extra round to wrap around. - if (64 - d.buf_len < 8) { - d.round(d.buf[0..]); - mem.set(u8, d.buf[0..], 0); + d.total_len += b.len; } - // Append message length. - var i: usize = 1; - var len = d.total_len >> 5; - d.buf[63] = u8(d.total_len & 0x1f) << 3; - while (i < 8) : (i += 1) { - d.buf[63 - i] = u8(len & 0xff); - len >>= 8; - } + pub fn final(d: *Self, out: []u8) void { + debug.assert(out.len >= params.out_len / 8); - d.round(d.buf[0..]); + // The buffer here will never be completely full. + mem.set(u8, d.buf[d.buf_len..], 0); - // May truncate for possible 224 output - const rr = d.s[0 .. params.out_len / 32]; + // Append padding bits. + d.buf[d.buf_len] = 0x80; + d.buf_len += 1; - for (rr) |s, j| { - mem.writeInt(out[4*j .. 4*j + 4], s, builtin.Endian.Big); - } - } + // > 448 mod 512 so need to add an extra round to wrap around. + if (64 - d.buf_len < 8) { + d.round(d.buf[0..]); + mem.set(u8, d.buf[0..], 0); + } + + // Append message length. + var i: usize = 1; + var len = d.total_len >> 5; + d.buf[63] = @intCast(u8, d.total_len & 0x1f) << 3; + while (i < 8) : (i += 1) { + d.buf[63 - i] = @intCast(u8, len & 0xff); + len >>= 8; + } - fn round(d: &Self, b: []const u8) void { - debug.assert(b.len == 64); + d.round(d.buf[0..]); - var s: [64]u32 = undefined; + // May truncate for possible 224 output + const rr = d.s[0 .. params.out_len / 32]; - var i: usize = 0; - while (i < 16) : (i += 1) { - s[i] = 0; - s[i] |= u32(b[i*4+0]) << 24; - s[i] |= u32(b[i*4+1]) << 16; - s[i] |= u32(b[i*4+2]) << 8; - s[i] |= u32(b[i*4+3]) << 0; - } - while (i < 64) : (i += 1) { - s[i] = - s[i-16] +% s[i-7] +% - (math.rotr(u32, s[i-15], u32(7)) ^ math.rotr(u32, s[i-15], u32(18)) ^ (s[i-15] >> 3)) +% - (math.rotr(u32, s[i-2], u32(17)) ^ math.rotr(u32, s[i-2], u32(19)) ^ (s[i-2] >> 10)); + for (rr) |s, j| { + mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big); + } } - var v: [8]u32 = []u32 { - d.s[0], d.s[1], d.s[2], d.s[3], d.s[4], d.s[5], d.s[6], d.s[7], - }; - - const round0 = comptime []RoundParam256 { - Rp256(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98), - Rp256(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x71374491), - Rp256(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCF), - Rp256(5, 6, 7, 0, 1, 2, 3, 4, 3, 0xE9B5DBA5), - Rp256(4, 5, 6, 7, 0, 1, 2, 3, 4, 0x3956C25B), - Rp256(3, 4, 5, 6, 7, 0, 1, 2, 5, 0x59F111F1), - Rp256(2, 3, 4, 5, 6, 7, 0, 1, 6, 0x923F82A4), - Rp256(1, 2, 3, 4, 5, 6, 7, 0, 7, 0xAB1C5ED5), - Rp256(0, 1, 2, 3, 4, 5, 6, 7, 8, 0xD807AA98), - Rp256(7, 0, 1, 2, 3, 4, 5, 6, 9, 0x12835B01), - Rp256(6, 7, 0, 1, 2, 3, 4, 5, 10, 0x243185BE), - Rp256(5, 6, 7, 0, 1, 2, 3, 4, 11, 0x550C7DC3), - Rp256(4, 5, 6, 7, 0, 1, 2, 3, 12, 0x72BE5D74), - Rp256(3, 4, 5, 6, 7, 0, 1, 2, 13, 0x80DEB1FE), - Rp256(2, 3, 4, 5, 6, 7, 0, 1, 14, 0x9BDC06A7), - Rp256(1, 2, 3, 4, 5, 6, 7, 0, 15, 0xC19BF174), - Rp256(0, 1, 2, 3, 4, 5, 6, 7, 16, 0xE49B69C1), - Rp256(7, 0, 1, 2, 3, 4, 5, 6, 17, 0xEFBE4786), - Rp256(6, 7, 0, 1, 2, 3, 4, 5, 18, 0x0FC19DC6), - Rp256(5, 6, 7, 0, 1, 2, 3, 4, 19, 0x240CA1CC), - Rp256(4, 5, 6, 7, 0, 1, 2, 3, 20, 0x2DE92C6F), - Rp256(3, 4, 5, 6, 7, 0, 1, 2, 21, 0x4A7484AA), - Rp256(2, 3, 4, 5, 6, 7, 0, 1, 22, 0x5CB0A9DC), - Rp256(1, 2, 3, 4, 5, 6, 7, 0, 23, 0x76F988DA), - Rp256(0, 1, 2, 3, 4, 5, 6, 7, 24, 0x983E5152), - Rp256(7, 0, 1, 2, 3, 4, 5, 6, 25, 0xA831C66D), - Rp256(6, 7, 0, 1, 2, 3, 4, 5, 26, 0xB00327C8), - Rp256(5, 6, 7, 0, 1, 2, 3, 4, 27, 0xBF597FC7), - Rp256(4, 5, 6, 7, 0, 1, 2, 3, 28, 0xC6E00BF3), - Rp256(3, 4, 5, 6, 7, 0, 1, 2, 29, 0xD5A79147), - Rp256(2, 3, 4, 5, 6, 7, 0, 1, 30, 0x06CA6351), - Rp256(1, 2, 3, 4, 5, 6, 7, 0, 31, 0x14292967), - Rp256(0, 1, 2, 3, 4, 5, 6, 7, 32, 0x27B70A85), - Rp256(7, 0, 1, 2, 3, 4, 5, 6, 33, 0x2E1B2138), - Rp256(6, 7, 0, 1, 2, 3, 4, 5, 34, 0x4D2C6DFC), - Rp256(5, 6, 7, 0, 1, 2, 3, 4, 35, 0x53380D13), - Rp256(4, 5, 6, 7, 0, 1, 2, 3, 36, 0x650A7354), - Rp256(3, 4, 5, 6, 7, 0, 1, 2, 37, 0x766A0ABB), - Rp256(2, 3, 4, 5, 6, 7, 0, 1, 38, 0x81C2C92E), - Rp256(1, 2, 3, 4, 5, 6, 7, 0, 39, 0x92722C85), - Rp256(0, 1, 2, 3, 4, 5, 6, 7, 40, 0xA2BFE8A1), - Rp256(7, 0, 1, 2, 3, 4, 5, 6, 41, 0xA81A664B), - Rp256(6, 7, 0, 1, 2, 3, 4, 5, 42, 0xC24B8B70), - Rp256(5, 6, 7, 0, 1, 2, 3, 4, 43, 0xC76C51A3), - Rp256(4, 5, 6, 7, 0, 1, 2, 3, 44, 0xD192E819), - Rp256(3, 4, 5, 6, 7, 0, 1, 2, 45, 0xD6990624), - Rp256(2, 3, 4, 5, 6, 7, 0, 1, 46, 0xF40E3585), - Rp256(1, 2, 3, 4, 5, 6, 7, 0, 47, 0x106AA070), - Rp256(0, 1, 2, 3, 4, 5, 6, 7, 48, 0x19A4C116), - Rp256(7, 0, 1, 2, 3, 4, 5, 6, 49, 0x1E376C08), - Rp256(6, 7, 0, 1, 2, 3, 4, 5, 50, 0x2748774C), - Rp256(5, 6, 7, 0, 1, 2, 3, 4, 51, 0x34B0BCB5), - Rp256(4, 5, 6, 7, 0, 1, 2, 3, 52, 0x391C0CB3), - Rp256(3, 4, 5, 6, 7, 0, 1, 2, 53, 0x4ED8AA4A), - Rp256(2, 3, 4, 5, 6, 7, 0, 1, 54, 0x5B9CCA4F), - Rp256(1, 2, 3, 4, 5, 6, 7, 0, 55, 0x682E6FF3), - Rp256(0, 1, 2, 3, 4, 5, 6, 7, 56, 0x748F82EE), - Rp256(7, 0, 1, 2, 3, 4, 5, 6, 57, 0x78A5636F), - Rp256(6, 7, 0, 1, 2, 3, 4, 5, 58, 0x84C87814), - Rp256(5, 6, 7, 0, 1, 2, 3, 4, 59, 0x8CC70208), - Rp256(4, 5, 6, 7, 0, 1, 2, 3, 60, 0x90BEFFFA), - Rp256(3, 4, 5, 6, 7, 0, 1, 2, 61, 0xA4506CEB), - Rp256(2, 3, 4, 5, 6, 7, 0, 1, 62, 0xBEF9A3F7), - Rp256(1, 2, 3, 4, 5, 6, 7, 0, 63, 0xC67178F2), - }; - inline for (round0) |r| { - v[r.h] = - v[r.h] +% - (math.rotr(u32, v[r.e], u32(6)) ^ math.rotr(u32, v[r.e], u32(11)) ^ math.rotr(u32, v[r.e], u32(25))) +% - (v[r.g] ^ (v[r.e] & (v[r.f] ^ v[r.g]))) +% - r.k +% s[r.i]; - - v[r.d] = v[r.d] +% v[r.h]; - - v[r.h] = - v[r.h] +% - (math.rotr(u32, v[r.a], u32(2)) ^ math.rotr(u32, v[r.a], u32(13)) ^ math.rotr(u32, v[r.a], u32(22))) +% - ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c])); + fn round(d: *Self, b: []const u8) void { + debug.assert(b.len == 64); + + var s: [64]u32 = undefined; + + var i: usize = 0; + while (i < 16) : (i += 1) { + s[i] = 0; + s[i] |= u32(b[i * 4 + 0]) << 24; + s[i] |= u32(b[i * 4 + 1]) << 16; + s[i] |= u32(b[i * 4 + 2]) << 8; + s[i] |= u32(b[i * 4 + 3]) << 0; + } + while (i < 64) : (i += 1) { + s[i] = s[i - 16] +% s[i - 7] +% (math.rotr(u32, s[i - 15], u32(7)) ^ math.rotr(u32, s[i - 15], u32(18)) ^ (s[i - 15] >> 3)) +% (math.rotr(u32, s[i - 2], u32(17)) ^ math.rotr(u32, s[i - 2], u32(19)) ^ (s[i - 2] >> 10)); + } + + var v: [8]u32 = []u32{ + d.s[0], + d.s[1], + d.s[2], + d.s[3], + d.s[4], + d.s[5], + d.s[6], + d.s[7], + }; + + const round0 = comptime []RoundParam256{ + Rp256(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98), + Rp256(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x71374491), + Rp256(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCF), + Rp256(5, 6, 7, 0, 1, 2, 3, 4, 3, 0xE9B5DBA5), + Rp256(4, 5, 6, 7, 0, 1, 2, 3, 4, 0x3956C25B), + Rp256(3, 4, 5, 6, 7, 0, 1, 2, 5, 0x59F111F1), + Rp256(2, 3, 4, 5, 6, 7, 0, 1, 6, 0x923F82A4), + Rp256(1, 2, 3, 4, 5, 6, 7, 0, 7, 0xAB1C5ED5), + Rp256(0, 1, 2, 3, 4, 5, 6, 7, 8, 0xD807AA98), + Rp256(7, 0, 1, 2, 3, 4, 5, 6, 9, 0x12835B01), + Rp256(6, 7, 0, 1, 2, 3, 4, 5, 10, 0x243185BE), + Rp256(5, 6, 7, 0, 1, 2, 3, 4, 11, 0x550C7DC3), + Rp256(4, 5, 6, 7, 0, 1, 2, 3, 12, 0x72BE5D74), + Rp256(3, 4, 5, 6, 7, 0, 1, 2, 13, 0x80DEB1FE), + Rp256(2, 3, 4, 5, 6, 7, 0, 1, 14, 0x9BDC06A7), + Rp256(1, 2, 3, 4, 5, 6, 7, 0, 15, 0xC19BF174), + Rp256(0, 1, 2, 3, 4, 5, 6, 7, 16, 0xE49B69C1), + Rp256(7, 0, 1, 2, 3, 4, 5, 6, 17, 0xEFBE4786), + Rp256(6, 7, 0, 1, 2, 3, 4, 5, 18, 0x0FC19DC6), + Rp256(5, 6, 7, 0, 1, 2, 3, 4, 19, 0x240CA1CC), + Rp256(4, 5, 6, 7, 0, 1, 2, 3, 20, 0x2DE92C6F), + Rp256(3, 4, 5, 6, 7, 0, 1, 2, 21, 0x4A7484AA), + Rp256(2, 3, 4, 5, 6, 7, 0, 1, 22, 0x5CB0A9DC), + Rp256(1, 2, 3, 4, 5, 6, 7, 0, 23, 0x76F988DA), + Rp256(0, 1, 2, 3, 4, 5, 6, 7, 24, 0x983E5152), + Rp256(7, 0, 1, 2, 3, 4, 5, 6, 25, 0xA831C66D), + Rp256(6, 7, 0, 1, 2, 3, 4, 5, 26, 0xB00327C8), + Rp256(5, 6, 7, 0, 1, 2, 3, 4, 27, 0xBF597FC7), + Rp256(4, 5, 6, 7, 0, 1, 2, 3, 28, 0xC6E00BF3), + Rp256(3, 4, 5, 6, 7, 0, 1, 2, 29, 0xD5A79147), + Rp256(2, 3, 4, 5, 6, 7, 0, 1, 30, 0x06CA6351), + Rp256(1, 2, 3, 4, 5, 6, 7, 0, 31, 0x14292967), + Rp256(0, 1, 2, 3, 4, 5, 6, 7, 32, 0x27B70A85), + Rp256(7, 0, 1, 2, 3, 4, 5, 6, 33, 0x2E1B2138), + Rp256(6, 7, 0, 1, 2, 3, 4, 5, 34, 0x4D2C6DFC), + Rp256(5, 6, 7, 0, 1, 2, 3, 4, 35, 0x53380D13), + Rp256(4, 5, 6, 7, 0, 1, 2, 3, 36, 0x650A7354), + Rp256(3, 4, 5, 6, 7, 0, 1, 2, 37, 0x766A0ABB), + Rp256(2, 3, 4, 5, 6, 7, 0, 1, 38, 0x81C2C92E), + Rp256(1, 2, 3, 4, 5, 6, 7, 0, 39, 0x92722C85), + Rp256(0, 1, 2, 3, 4, 5, 6, 7, 40, 0xA2BFE8A1), + Rp256(7, 0, 1, 2, 3, 4, 5, 6, 41, 0xA81A664B), + Rp256(6, 7, 0, 1, 2, 3, 4, 5, 42, 0xC24B8B70), + Rp256(5, 6, 7, 0, 1, 2, 3, 4, 43, 0xC76C51A3), + Rp256(4, 5, 6, 7, 0, 1, 2, 3, 44, 0xD192E819), + Rp256(3, 4, 5, 6, 7, 0, 1, 2, 45, 0xD6990624), + Rp256(2, 3, 4, 5, 6, 7, 0, 1, 46, 0xF40E3585), + Rp256(1, 2, 3, 4, 5, 6, 7, 0, 47, 0x106AA070), + Rp256(0, 1, 2, 3, 4, 5, 6, 7, 48, 0x19A4C116), + Rp256(7, 0, 1, 2, 3, 4, 5, 6, 49, 0x1E376C08), + Rp256(6, 7, 0, 1, 2, 3, 4, 5, 50, 0x2748774C), + Rp256(5, 6, 7, 0, 1, 2, 3, 4, 51, 0x34B0BCB5), + Rp256(4, 5, 6, 7, 0, 1, 2, 3, 52, 0x391C0CB3), + Rp256(3, 4, 5, 6, 7, 0, 1, 2, 53, 0x4ED8AA4A), + Rp256(2, 3, 4, 5, 6, 7, 0, 1, 54, 0x5B9CCA4F), + Rp256(1, 2, 3, 4, 5, 6, 7, 0, 55, 0x682E6FF3), + Rp256(0, 1, 2, 3, 4, 5, 6, 7, 56, 0x748F82EE), + Rp256(7, 0, 1, 2, 3, 4, 5, 6, 57, 0x78A5636F), + Rp256(6, 7, 0, 1, 2, 3, 4, 5, 58, 0x84C87814), + Rp256(5, 6, 7, 0, 1, 2, 3, 4, 59, 0x8CC70208), + Rp256(4, 5, 6, 7, 0, 1, 2, 3, 60, 0x90BEFFFA), + Rp256(3, 4, 5, 6, 7, 0, 1, 2, 61, 0xA4506CEB), + Rp256(2, 3, 4, 5, 6, 7, 0, 1, 62, 0xBEF9A3F7), + Rp256(1, 2, 3, 4, 5, 6, 7, 0, 63, 0xC67178F2), + }; + inline for (round0) |r| { + v[r.h] = v[r.h] +% (math.rotr(u32, v[r.e], u32(6)) ^ math.rotr(u32, v[r.e], u32(11)) ^ math.rotr(u32, v[r.e], u32(25))) +% (v[r.g] ^ (v[r.e] & (v[r.f] ^ v[r.g]))) +% r.k +% s[r.i]; + + v[r.d] = v[r.d] +% v[r.h]; + + v[r.h] = v[r.h] +% (math.rotr(u32, v[r.a], u32(2)) ^ math.rotr(u32, v[r.a], u32(13)) ^ math.rotr(u32, v[r.a], u32(22))) +% ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c])); + } + + d.s[0] +%= v[0]; + d.s[1] +%= v[1]; + d.s[2] +%= v[2]; + d.s[3] +%= v[3]; + d.s[4] +%= v[4]; + d.s[5] +%= v[5]; + d.s[6] +%= v[6]; + d.s[7] +%= v[7]; } - - d.s[0] +%= v[0]; - d.s[1] +%= v[1]; - d.s[2] +%= v[2]; - d.s[3] +%= v[3]; - d.s[4] +%= v[4]; - d.s[5] +%= v[5]; - d.s[6] +%= v[6]; - d.s[7] +%= v[7]; - } -};} + }; +} test "sha224 single" { htest.assertEqualHash(Sha224, "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", ""); @@ -320,7 +338,7 @@ test "sha256 streaming" { } test "sha256 aligned final" { - var block = []u8 {0} ** Sha256.block_size; + var block = []u8{0} ** Sha256.block_size; var out: [Sha256.digest_size]u8 = undefined; var h = Sha256.init(); @@ -328,17 +346,35 @@ test "sha256 aligned final" { h.final(out[0..]); } - ///////////////////// // Sha384 + Sha512 const RoundParam512 = struct { - a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, - i: usize, k: u64, + a: usize, + b: usize, + c: usize, + d: usize, + e: usize, + f: usize, + g: usize, + h: usize, + i: usize, + k: u64, }; fn Rp512(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u64) RoundParam512 { - return RoundParam512 { .a = a, .b = b, .c = c, .d = d, .e = e, .f = f, .g = g, .h = h, .i = i, .k = k }; + return RoundParam512{ + .a = a, + .b = b, + .c = c, + .d = d, + .e = e, + .f = f, + .g = g, + .h = h, + .i = i, + .k = k, + }; } const Sha2Params64 = struct { @@ -353,7 +389,7 @@ const Sha2Params64 = struct { out_len: usize, }; -const Sha384Params = Sha2Params64 { +const Sha384Params = Sha2Params64{ .iv0 = 0xCBBB9D5DC1059ED8, .iv1 = 0x629A292A367CD507, .iv2 = 0x9159015A3070DD17, @@ -365,7 +401,7 @@ const Sha384Params = Sha2Params64 { .out_len = 384, }; -const Sha512Params = Sha2Params64 { +const Sha512Params = Sha2Params64{ .iv0 = 0x6A09E667F3BCC908, .iv1 = 0xBB67AE8584CAA73B, .iv2 = 0x3C6EF372FE94F82B, @@ -374,242 +410,241 @@ const Sha512Params = Sha2Params64 { .iv5 = 0x9B05688C2B3E6C1F, .iv6 = 0x1F83D9ABFB41BD6B, .iv7 = 0x5BE0CD19137E2179, - .out_len = 512 + .out_len = 512, }; pub const Sha384 = Sha2_64(Sha384Params); pub const Sha512 = Sha2_64(Sha512Params); -fn Sha2_64(comptime params: Sha2Params64) type { return struct { - const Self = this; - const block_size = 128; - const digest_size = params.out_len / 8; - - s: [8]u64, - // Streaming Cache - buf: [128]u8, - buf_len: u8, - total_len: u128, - - pub fn init() Self { - var d: Self = undefined; - d.reset(); - return d; - } - - pub fn reset(d: &Self) void { - d.s[0] = params.iv0; - d.s[1] = params.iv1; - d.s[2] = params.iv2; - d.s[3] = params.iv3; - d.s[4] = params.iv4; - d.s[5] = params.iv5; - d.s[6] = params.iv6; - d.s[7] = params.iv7; - d.buf_len = 0; - d.total_len = 0; - } - - pub fn hash(b: []const u8, out: []u8) void { - var d = Self.init(); - d.update(b); - d.final(out); - } - - pub fn update(d: &Self, b: []const u8) void { - var off: usize = 0; - - // Partial buffer exists from previous update. Copy into buffer then hash. - if (d.buf_len != 0 and d.buf_len + b.len > 128) { - off += 128 - d.buf_len; - mem.copy(u8, d.buf[d.buf_len..], b[0..off]); +fn Sha2_64(comptime params: Sha2Params64) type { + return struct { + const Self = this; + const block_size = 128; + const digest_size = params.out_len / 8; + + s: [8]u64, + // Streaming Cache + buf: [128]u8, + buf_len: u8, + total_len: u128, + + pub fn init() Self { + var d: Self = undefined; + d.reset(); + return d; + } - d.round(d.buf[0..]); + pub fn reset(d: *Self) void { + d.s[0] = params.iv0; + d.s[1] = params.iv1; + d.s[2] = params.iv2; + d.s[3] = params.iv3; + d.s[4] = params.iv4; + d.s[5] = params.iv5; + d.s[6] = params.iv6; + d.s[7] = params.iv7; d.buf_len = 0; + d.total_len = 0; } - // Full middle blocks. - while (off + 128 <= b.len) : (off += 128) { - d.round(b[off..off + 128]); + pub fn hash(b: []const u8, out: []u8) void { + var d = Self.init(); + d.update(b); + d.final(out); } - // Copy any remainder for next pass. - mem.copy(u8, d.buf[d.buf_len..], b[off..]); - d.buf_len += u8(b[off..].len); + pub fn update(d: *Self, b: []const u8) void { + var off: usize = 0; - d.total_len += b.len; - } + // Partial buffer exists from previous update. Copy into buffer then hash. + if (d.buf_len != 0 and d.buf_len + b.len > 128) { + off += 128 - d.buf_len; + mem.copy(u8, d.buf[d.buf_len..], b[0..off]); - pub fn final(d: &Self, out: []u8) void { - debug.assert(out.len >= params.out_len / 8); + d.round(d.buf[0..]); + d.buf_len = 0; + } - // The buffer here will never be completely full. - mem.set(u8, d.buf[d.buf_len..], 0); + // Full middle blocks. + while (off + 128 <= b.len) : (off += 128) { + d.round(b[off .. off + 128]); + } - // Append padding bits. - d.buf[d.buf_len] = 0x80; - d.buf_len += 1; + // Copy any remainder for next pass. + mem.copy(u8, d.buf[d.buf_len..], b[off..]); + d.buf_len += @intCast(u8, b[off..].len); - // > 896 mod 1024 so need to add an extra round to wrap around. - if (128 - d.buf_len < 16) { - d.round(d.buf[0..]); - mem.set(u8, d.buf[0..], 0); + d.total_len += b.len; } - // Append message length. - var i: usize = 1; - var len = d.total_len >> 5; - d.buf[127] = u8(d.total_len & 0x1f) << 3; - while (i < 16) : (i += 1) { - d.buf[127 - i] = u8(len & 0xff); - len >>= 8; - } + pub fn final(d: *Self, out: []u8) void { + debug.assert(out.len >= params.out_len / 8); - d.round(d.buf[0..]); + // The buffer here will never be completely full. + mem.set(u8, d.buf[d.buf_len..], 0); - // May truncate for possible 384 output - const rr = d.s[0 .. params.out_len / 64]; + // Append padding bits. + d.buf[d.buf_len] = 0x80; + d.buf_len += 1; - for (rr) |s, j| { - mem.writeInt(out[8*j .. 8*j + 8], s, builtin.Endian.Big); - } - } - - fn round(d: &Self, b: []const u8) void { - debug.assert(b.len == 128); - - var s: [80]u64 = undefined; - - var i: usize = 0; - while (i < 16) : (i += 1) { - s[i] = 0; - s[i] |= u64(b[i*8+0]) << 56; - s[i] |= u64(b[i*8+1]) << 48; - s[i] |= u64(b[i*8+2]) << 40; - s[i] |= u64(b[i*8+3]) << 32; - s[i] |= u64(b[i*8+4]) << 24; - s[i] |= u64(b[i*8+5]) << 16; - s[i] |= u64(b[i*8+6]) << 8; - s[i] |= u64(b[i*8+7]) << 0; - } - while (i < 80) : (i += 1) { - s[i] = - s[i-16] +% s[i-7] +% - (math.rotr(u64, s[i-15], u64(1)) ^ math.rotr(u64, s[i-15], u64(8)) ^ (s[i-15] >> 7)) +% - (math.rotr(u64, s[i-2], u64(19)) ^ math.rotr(u64, s[i-2], u64(61)) ^ (s[i-2] >> 6)); - } + // > 896 mod 1024 so need to add an extra round to wrap around. + if (128 - d.buf_len < 16) { + d.round(d.buf[0..]); + mem.set(u8, d.buf[0..], 0); + } - var v: [8]u64 = []u64 { - d.s[0], d.s[1], d.s[2], d.s[3], d.s[4], d.s[5], d.s[6], d.s[7], - }; - - const round0 = comptime []RoundParam512 { - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98D728AE22), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x7137449123EF65CD), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCFEC4D3B2F), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 3, 0xE9B5DBA58189DBBC), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 4, 0x3956C25BF348B538), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 5, 0x59F111F1B605D019), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 6, 0x923F82A4AF194F9B), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 7, 0xAB1C5ED5DA6D8118), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 8, 0xD807AA98A3030242), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 9, 0x12835B0145706FBE), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 10, 0x243185BE4EE4B28C), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 11, 0x550C7DC3D5FFB4E2), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 12, 0x72BE5D74F27B896F), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 13, 0x80DEB1FE3B1696B1), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 14, 0x9BDC06A725C71235), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 15, 0xC19BF174CF692694), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 16, 0xE49B69C19EF14AD2), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 17, 0xEFBE4786384F25E3), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 18, 0x0FC19DC68B8CD5B5), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 19, 0x240CA1CC77AC9C65), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 20, 0x2DE92C6F592B0275), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 21, 0x4A7484AA6EA6E483), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 22, 0x5CB0A9DCBD41FBD4), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 23, 0x76F988DA831153B5), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 24, 0x983E5152EE66DFAB), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 25, 0xA831C66D2DB43210), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 26, 0xB00327C898FB213F), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 27, 0xBF597FC7BEEF0EE4), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 28, 0xC6E00BF33DA88FC2), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 29, 0xD5A79147930AA725), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 30, 0x06CA6351E003826F), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 31, 0x142929670A0E6E70), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 32, 0x27B70A8546D22FFC), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 33, 0x2E1B21385C26C926), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 34, 0x4D2C6DFC5AC42AED), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 35, 0x53380D139D95B3DF), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 36, 0x650A73548BAF63DE), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 37, 0x766A0ABB3C77B2A8), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 38, 0x81C2C92E47EDAEE6), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 39, 0x92722C851482353B), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 40, 0xA2BFE8A14CF10364), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 41, 0xA81A664BBC423001), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 42, 0xC24B8B70D0F89791), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 43, 0xC76C51A30654BE30), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 44, 0xD192E819D6EF5218), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 45, 0xD69906245565A910), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 46, 0xF40E35855771202A), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 47, 0x106AA07032BBD1B8), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 48, 0x19A4C116B8D2D0C8), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 49, 0x1E376C085141AB53), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 50, 0x2748774CDF8EEB99), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 51, 0x34B0BCB5E19B48A8), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 52, 0x391C0CB3C5C95A63), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 53, 0x4ED8AA4AE3418ACB), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 54, 0x5B9CCA4F7763E373), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 55, 0x682E6FF3D6B2B8A3), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 56, 0x748F82EE5DEFB2FC), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 57, 0x78A5636F43172F60), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 58, 0x84C87814A1F0AB72), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 59, 0x8CC702081A6439EC), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 60, 0x90BEFFFA23631E28), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 61, 0xA4506CEBDE82BDE9), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 62, 0xBEF9A3F7B2C67915), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 63, 0xC67178F2E372532B), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 64, 0xCA273ECEEA26619C), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 65, 0xD186B8C721C0C207), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 66, 0xEADA7DD6CDE0EB1E), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 67, 0xF57D4F7FEE6ED178), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 68, 0x06F067AA72176FBA), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 69, 0x0A637DC5A2C898A6), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 70, 0x113F9804BEF90DAE), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 71, 0x1B710B35131C471B), - Rp512(0, 1, 2, 3, 4, 5, 6, 7, 72, 0x28DB77F523047D84), - Rp512(7, 0, 1, 2, 3, 4, 5, 6, 73, 0x32CAAB7B40C72493), - Rp512(6, 7, 0, 1, 2, 3, 4, 5, 74, 0x3C9EBE0A15C9BEBC), - Rp512(5, 6, 7, 0, 1, 2, 3, 4, 75, 0x431D67C49C100D4C), - Rp512(4, 5, 6, 7, 0, 1, 2, 3, 76, 0x4CC5D4BECB3E42B6), - Rp512(3, 4, 5, 6, 7, 0, 1, 2, 77, 0x597F299CFC657E2A), - Rp512(2, 3, 4, 5, 6, 7, 0, 1, 78, 0x5FCB6FAB3AD6FAEC), - Rp512(1, 2, 3, 4, 5, 6, 7, 0, 79, 0x6C44198C4A475817), - }; - inline for (round0) |r| { - v[r.h] = - v[r.h] +% - (math.rotr(u64, v[r.e], u64(14)) ^ math.rotr(u64, v[r.e], u64(18)) ^ math.rotr(u64, v[r.e], u64(41))) +% - (v[r.g] ^ (v[r.e] & (v[r.f] ^ v[r.g]))) +% - r.k +% s[r.i]; - - v[r.d] = v[r.d] +% v[r.h]; - - v[r.h] = - v[r.h] +% - (math.rotr(u64, v[r.a], u64(28)) ^ math.rotr(u64, v[r.a], u64(34)) ^ math.rotr(u64, v[r.a], u64(39))) +% - ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c])); + // Append message length. + var i: usize = 1; + var len = d.total_len >> 5; + d.buf[127] = @intCast(u8, d.total_len & 0x1f) << 3; + while (i < 16) : (i += 1) { + d.buf[127 - i] = @intCast(u8, len & 0xff); + len >>= 8; + } + + d.round(d.buf[0..]); + + // May truncate for possible 384 output + const rr = d.s[0 .. params.out_len / 64]; + + for (rr) |s, j| { + mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Big); + } } - d.s[0] +%= v[0]; - d.s[1] +%= v[1]; - d.s[2] +%= v[2]; - d.s[3] +%= v[3]; - d.s[4] +%= v[4]; - d.s[5] +%= v[5]; - d.s[6] +%= v[6]; - d.s[7] +%= v[7]; - } -};} + fn round(d: *Self, b: []const u8) void { + debug.assert(b.len == 128); + + var s: [80]u64 = undefined; + + var i: usize = 0; + while (i < 16) : (i += 1) { + s[i] = 0; + s[i] |= u64(b[i * 8 + 0]) << 56; + s[i] |= u64(b[i * 8 + 1]) << 48; + s[i] |= u64(b[i * 8 + 2]) << 40; + s[i] |= u64(b[i * 8 + 3]) << 32; + s[i] |= u64(b[i * 8 + 4]) << 24; + s[i] |= u64(b[i * 8 + 5]) << 16; + s[i] |= u64(b[i * 8 + 6]) << 8; + s[i] |= u64(b[i * 8 + 7]) << 0; + } + while (i < 80) : (i += 1) { + s[i] = s[i - 16] +% s[i - 7] +% (math.rotr(u64, s[i - 15], u64(1)) ^ math.rotr(u64, s[i - 15], u64(8)) ^ (s[i - 15] >> 7)) +% (math.rotr(u64, s[i - 2], u64(19)) ^ math.rotr(u64, s[i - 2], u64(61)) ^ (s[i - 2] >> 6)); + } + + var v: [8]u64 = []u64{ + d.s[0], + d.s[1], + d.s[2], + d.s[3], + d.s[4], + d.s[5], + d.s[6], + d.s[7], + }; + + const round0 = comptime []RoundParam512{ + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98D728AE22), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x7137449123EF65CD), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCFEC4D3B2F), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 3, 0xE9B5DBA58189DBBC), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 4, 0x3956C25BF348B538), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 5, 0x59F111F1B605D019), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 6, 0x923F82A4AF194F9B), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 7, 0xAB1C5ED5DA6D8118), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 8, 0xD807AA98A3030242), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 9, 0x12835B0145706FBE), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 10, 0x243185BE4EE4B28C), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 11, 0x550C7DC3D5FFB4E2), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 12, 0x72BE5D74F27B896F), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 13, 0x80DEB1FE3B1696B1), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 14, 0x9BDC06A725C71235), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 15, 0xC19BF174CF692694), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 16, 0xE49B69C19EF14AD2), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 17, 0xEFBE4786384F25E3), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 18, 0x0FC19DC68B8CD5B5), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 19, 0x240CA1CC77AC9C65), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 20, 0x2DE92C6F592B0275), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 21, 0x4A7484AA6EA6E483), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 22, 0x5CB0A9DCBD41FBD4), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 23, 0x76F988DA831153B5), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 24, 0x983E5152EE66DFAB), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 25, 0xA831C66D2DB43210), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 26, 0xB00327C898FB213F), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 27, 0xBF597FC7BEEF0EE4), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 28, 0xC6E00BF33DA88FC2), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 29, 0xD5A79147930AA725), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 30, 0x06CA6351E003826F), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 31, 0x142929670A0E6E70), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 32, 0x27B70A8546D22FFC), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 33, 0x2E1B21385C26C926), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 34, 0x4D2C6DFC5AC42AED), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 35, 0x53380D139D95B3DF), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 36, 0x650A73548BAF63DE), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 37, 0x766A0ABB3C77B2A8), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 38, 0x81C2C92E47EDAEE6), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 39, 0x92722C851482353B), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 40, 0xA2BFE8A14CF10364), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 41, 0xA81A664BBC423001), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 42, 0xC24B8B70D0F89791), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 43, 0xC76C51A30654BE30), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 44, 0xD192E819D6EF5218), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 45, 0xD69906245565A910), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 46, 0xF40E35855771202A), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 47, 0x106AA07032BBD1B8), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 48, 0x19A4C116B8D2D0C8), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 49, 0x1E376C085141AB53), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 50, 0x2748774CDF8EEB99), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 51, 0x34B0BCB5E19B48A8), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 52, 0x391C0CB3C5C95A63), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 53, 0x4ED8AA4AE3418ACB), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 54, 0x5B9CCA4F7763E373), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 55, 0x682E6FF3D6B2B8A3), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 56, 0x748F82EE5DEFB2FC), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 57, 0x78A5636F43172F60), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 58, 0x84C87814A1F0AB72), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 59, 0x8CC702081A6439EC), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 60, 0x90BEFFFA23631E28), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 61, 0xA4506CEBDE82BDE9), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 62, 0xBEF9A3F7B2C67915), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 63, 0xC67178F2E372532B), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 64, 0xCA273ECEEA26619C), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 65, 0xD186B8C721C0C207), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 66, 0xEADA7DD6CDE0EB1E), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 67, 0xF57D4F7FEE6ED178), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 68, 0x06F067AA72176FBA), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 69, 0x0A637DC5A2C898A6), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 70, 0x113F9804BEF90DAE), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 71, 0x1B710B35131C471B), + Rp512(0, 1, 2, 3, 4, 5, 6, 7, 72, 0x28DB77F523047D84), + Rp512(7, 0, 1, 2, 3, 4, 5, 6, 73, 0x32CAAB7B40C72493), + Rp512(6, 7, 0, 1, 2, 3, 4, 5, 74, 0x3C9EBE0A15C9BEBC), + Rp512(5, 6, 7, 0, 1, 2, 3, 4, 75, 0x431D67C49C100D4C), + Rp512(4, 5, 6, 7, 0, 1, 2, 3, 76, 0x4CC5D4BECB3E42B6), + Rp512(3, 4, 5, 6, 7, 0, 1, 2, 77, 0x597F299CFC657E2A), + Rp512(2, 3, 4, 5, 6, 7, 0, 1, 78, 0x5FCB6FAB3AD6FAEC), + Rp512(1, 2, 3, 4, 5, 6, 7, 0, 79, 0x6C44198C4A475817), + }; + inline for (round0) |r| { + v[r.h] = v[r.h] +% (math.rotr(u64, v[r.e], u64(14)) ^ math.rotr(u64, v[r.e], u64(18)) ^ math.rotr(u64, v[r.e], u64(41))) +% (v[r.g] ^ (v[r.e] & (v[r.f] ^ v[r.g]))) +% r.k +% s[r.i]; + + v[r.d] = v[r.d] +% v[r.h]; + + v[r.h] = v[r.h] +% (math.rotr(u64, v[r.a], u64(28)) ^ math.rotr(u64, v[r.a], u64(34)) ^ math.rotr(u64, v[r.a], u64(39))) +% ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c])); + } + + d.s[0] +%= v[0]; + d.s[1] +%= v[1]; + d.s[2] +%= v[2]; + d.s[3] +%= v[3]; + d.s[4] +%= v[4]; + d.s[5] +%= v[5]; + d.s[6] +%= v[6]; + d.s[7] +%= v[7]; + } + }; +} test "sha384 single" { const h1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"; @@ -680,7 +715,7 @@ test "sha512 streaming" { } test "sha512 aligned final" { - var block = []u8 {0} ** Sha512.block_size; + var block = []u8{0} ** Sha512.block_size; var out: [Sha512.digest_size]u8 = undefined; var h = Sha512.init(); diff --git a/std/crypto/sha3.zig b/std/crypto/sha3.zig index f92f56d68f..ae02d7a482 100644 --- a/std/crypto/sha3.zig +++ b/std/crypto/sha3.zig @@ -10,148 +10,228 @@ pub const Sha3_256 = Keccak(256, 0x06); pub const Sha3_384 = Keccak(384, 0x06); pub const Sha3_512 = Keccak(512, 0x06); -fn Keccak(comptime bits: usize, comptime delim: u8) type { return struct { - const Self = this; - const block_size = 200; - const digest_size = bits / 8; - - s: [200]u8, - offset: usize, - rate: usize, - - pub fn init() Self { - var d: Self = undefined; - d.reset(); - return d; - } +fn Keccak(comptime bits: usize, comptime delim: u8) type { + return struct { + const Self = this; + const block_size = 200; + const digest_size = bits / 8; + + s: [200]u8, + offset: usize, + rate: usize, + + pub fn init() Self { + var d: Self = undefined; + d.reset(); + return d; + } - pub fn reset(d: &Self) void { - mem.set(u8, d.s[0..], 0); - d.offset = 0; - d.rate = 200 - (bits / 4); - } + pub fn reset(d: *Self) void { + mem.set(u8, d.s[0..], 0); + d.offset = 0; + d.rate = 200 - (bits / 4); + } - pub fn hash(b: []const u8, out: []u8) void { - var d = Self.init(); - d.update(b); - d.final(out); - } + pub fn hash(b: []const u8, out: []u8) void { + var d = Self.init(); + d.update(b); + d.final(out); + } - pub fn update(d: &Self, b: []const u8) void { - var ip: usize = 0; - var len = b.len; - var rate = d.rate - d.offset; - var offset = d.offset; + pub fn update(d: *Self, b: []const u8) void { + var ip: usize = 0; + var len = b.len; + var rate = d.rate - d.offset; + var offset = d.offset; - // absorb - while (len >= rate) { - for (d.s[offset .. offset + rate]) |*r, i| - *r ^= b[ip..][i]; + // absorb + while (len >= rate) { + for (d.s[offset .. offset + rate]) |*r, i| + r.* ^= b[ip..][i]; - keccak_f(1600, d.s[0..]); + keccak_f(1600, d.s[0..]); - ip += rate; - len -= rate; - rate = d.rate; - offset = 0; - } + ip += rate; + len -= rate; + rate = d.rate; + offset = 0; + } - for (d.s[offset .. offset + len]) |*r, i| - *r ^= b[ip..][i]; + for (d.s[offset .. offset + len]) |*r, i| + r.* ^= b[ip..][i]; - d.offset = offset + len; - } + d.offset = offset + len; + } - pub fn final(d: &Self, out: []u8) void { - // padding - d.s[d.offset] ^= delim; - d.s[d.rate - 1] ^= 0x80; + pub fn final(d: *Self, out: []u8) void { + // padding + d.s[d.offset] ^= delim; + d.s[d.rate - 1] ^= 0x80; - keccak_f(1600, d.s[0..]); + keccak_f(1600, d.s[0..]); - // squeeze - var op: usize = 0; - var len: usize = bits / 8; + // squeeze + var op: usize = 0; + var len: usize = bits / 8; - while (len >= d.rate) { - mem.copy(u8, out[op..], d.s[0..d.rate]); - keccak_f(1600, d.s[0..]); - op += d.rate; - len -= d.rate; + while (len >= d.rate) { + mem.copy(u8, out[op..], d.s[0..d.rate]); + keccak_f(1600, d.s[0..]); + op += d.rate; + len -= d.rate; + } + + mem.copy(u8, out[op..], d.s[0..len]); } + }; +} - mem.copy(u8, out[op..], d.s[0..len]); - } -};} - -const RC = []const u64 { - 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000, - 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, - 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, - 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003, - 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a, - 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008, +const RC = []const u64{ + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808a, + 0x8000000080008000, + 0x000000000000808b, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008a, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000a, + 0x000000008000808b, + 0x800000000000008b, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800a, + 0x800000008000000a, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, }; -const ROTC = []const usize { - 1, 3, 6, 10, 15, 21, 28, 36, - 45, 55, 2, 14, 27, 41, 56, 8, - 25, 43, 62, 18, 39, 61, 20, 44 +const ROTC = []const usize{ + 1, + 3, + 6, + 10, + 15, + 21, + 28, + 36, + 45, + 55, + 2, + 14, + 27, + 41, + 56, + 8, + 25, + 43, + 62, + 18, + 39, + 61, + 20, + 44, }; -const PIL = []const usize { - 10, 7, 11, 17, 18, 3, 5, 16, - 8, 21, 24, 4, 15, 23, 19, 13, - 12, 2, 20, 14, 22, 9, 6, 1 +const PIL = []const usize{ + 10, + 7, + 11, + 17, + 18, + 3, + 5, + 16, + 8, + 21, + 24, + 4, + 15, + 23, + 19, + 13, + 12, + 2, + 20, + 14, + 22, + 9, + 6, + 1, }; -const M5 = []const usize { - 0, 1, 2, 3, 4, 0, 1, 2, 3, 4 +const M5 = []const usize{ + 0, + 1, + 2, + 3, + 4, + 0, + 1, + 2, + 3, + 4, }; fn keccak_f(comptime F: usize, d: []u8) void { debug.assert(d.len == F / 8); const B = F / 25; - const no_rounds = comptime x: { break :x 12 + 2 * math.log2(B); }; + const no_rounds = comptime x: { + break :x 12 + 2 * math.log2(B); + }; - var s = []const u64 {0} ** 25; - var t = []const u64 {0} ** 1; - var c = []const u64 {0} ** 5; + var s = []const u64{0} ** 25; + var t = []const u64{0} ** 1; + var c = []const u64{0} ** 5; for (s) |*r, i| { - *r = mem.readIntLE(u64, d[8*i .. 8*i + 8]); + r.* = mem.readIntLE(u64, d[8 * i .. 8 * i + 8]); } comptime var x: usize = 0; comptime var y: usize = 0; for (RC[0..no_rounds]) |round| { // theta - x = 0; inline while (x < 5) : (x += 1) { - c[x] = s[x] ^ s[x+5] ^ s[x+10] ^ s[x+15] ^ s[x+20]; + x = 0; + inline while (x < 5) : (x += 1) { + c[x] = s[x] ^ s[x + 5] ^ s[x + 10] ^ s[x + 15] ^ s[x + 20]; } - x = 0; inline while (x < 5) : (x += 1) { - t[0] = c[M5[x+4]] ^ math.rotl(u64, c[M5[x+1]], usize(1)); - y = 0; inline while (y < 5) : (y += 1) { - s[x + y*5] ^= t[0]; + x = 0; + inline while (x < 5) : (x += 1) { + t[0] = c[M5[x + 4]] ^ math.rotl(u64, c[M5[x + 1]], usize(1)); + y = 0; + inline while (y < 5) : (y += 1) { + s[x + y * 5] ^= t[0]; } } // rho+pi t[0] = s[1]; - x = 0; inline while (x < 24) : (x += 1) { + x = 0; + inline while (x < 24) : (x += 1) { c[0] = s[PIL[x]]; s[PIL[x]] = math.rotl(u64, t[0], ROTC[x]); t[0] = c[0]; } // chi - y = 0; inline while (y < 5) : (y += 1) { - x = 0; inline while (x < 5) : (x += 1) { - c[x] = s[x + y*5]; + y = 0; + inline while (y < 5) : (y += 1) { + x = 0; + inline while (x < 5) : (x += 1) { + c[x] = s[x + y * 5]; } - x = 0; inline while (x < 5) : (x += 1) { - s[x + y*5] = c[x] ^ (~c[M5[x+1]] & c[M5[x+2]]); + x = 0; + inline while (x < 5) : (x += 1) { + s[x + y * 5] = c[x] ^ (~c[M5[x + 1]] & c[M5[x + 2]]); } } @@ -160,11 +240,10 @@ fn keccak_f(comptime F: usize, d: []u8) void { } for (s) |r, i| { - mem.writeInt(d[8*i .. 8*i + 8], r, builtin.Endian.Little); + mem.writeInt(d[8 * i .. 8 * i + 8], r, builtin.Endian.Little); } } - test "sha3-224 single" { htest.assertEqualHash(Sha3_224, "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7", ""); htest.assertEqualHash(Sha3_224, "e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf", "abc"); @@ -192,7 +271,7 @@ test "sha3-224 streaming" { } test "sha3-256 single" { - htest.assertEqualHash(Sha3_256, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a" , ""); + htest.assertEqualHash(Sha3_256, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a", ""); htest.assertEqualHash(Sha3_256, "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532", "abc"); htest.assertEqualHash(Sha3_256, "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); } @@ -218,7 +297,7 @@ test "sha3-256 streaming" { } test "sha3-256 aligned final" { - var block = []u8 {0} ** Sha3_256.block_size; + var block = []u8{0} ** Sha3_256.block_size; var out: [Sha3_256.digest_size]u8 = undefined; var h = Sha3_256.init(); @@ -228,7 +307,7 @@ test "sha3-256 aligned final" { test "sha3-384 single" { const h1 = "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"; - htest.assertEqualHash(Sha3_384, h1 , ""); + htest.assertEqualHash(Sha3_384, h1, ""); const h2 = "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25"; htest.assertEqualHash(Sha3_384, h2, "abc"); const h3 = "79407d3b5916b59c3e30b09822974791c313fb9ecc849e406f23592d04f625dc8c709b98b43b3852b337216179aa7fc7"; @@ -259,7 +338,7 @@ test "sha3-384 streaming" { test "sha3-512 single" { const h1 = "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"; - htest.assertEqualHash(Sha3_512, h1 , ""); + htest.assertEqualHash(Sha3_512, h1, ""); const h2 = "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"; htest.assertEqualHash(Sha3_512, h2, "abc"); const h3 = "afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185"; @@ -289,7 +368,7 @@ test "sha3-512 streaming" { } test "sha3-512 aligned final" { - var block = []u8 {0} ** Sha3_512.block_size; + var block = []u8{0} ** Sha3_512.block_size; var out: [Sha3_512.digest_size]u8 = undefined; var h = Sha3_512.init(); diff --git a/std/crypto/test.zig b/std/crypto/test.zig index e41c6a7a2d..3fa24272e5 100644 --- a/std/crypto/test.zig +++ b/std/crypto/test.zig @@ -14,9 +14,8 @@ pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, inpu pub fn assertEqual(comptime expected: []const u8, input: []const u8) void { var expected_bytes: [expected.len / 2]u8 = undefined; for (expected_bytes) |*r, i| { - *r = fmt.parseInt(u8, expected[2*i .. 2*i+2], 16) catch unreachable; + r.* = fmt.parseInt(u8, expected[2 * i .. 2 * i + 2], 16) catch unreachable; } debug.assert(mem.eql(u8, expected_bytes, input)); } - diff --git a/std/crypto/throughput_test.zig b/std/crypto/throughput_test.zig index 60610411b5..c21838e607 100644 --- a/std/crypto/throughput_test.zig +++ b/std/crypto/throughput_test.zig @@ -1,22 +1,17 @@ // Modify the HashFunction variable to the one wanted to test. // -// NOTE: The throughput measurement may be slightly lower than other measurements since we run -// through our block alignment functions as well. Be aware when comparing against other tests. -// // ``` -// zig build-exe --release-fast --library c throughput_test.zig +// zig build-exe --release-fast throughput_test.zig // ./throughput_test // ``` -const HashFunction = @import("md5.zig").Md5; -const BytesToHash = 1024 * Mb; const std = @import("std"); +const time = std.os.time; +const Timer = time.Timer; +const HashFunction = @import("md5.zig").Md5; -const c = @cImport({ - @cInclude("time.h"); -}); - -const Mb = 1024 * 1024; +const MiB = 1024 * 1024; +const BytesToHash = 1024 * MiB; pub fn main() !void { var stdout_file = try std.io.getStdOut(); @@ -29,15 +24,15 @@ pub fn main() !void { var h = HashFunction.init(); var offset: usize = 0; - const start = c.clock(); + var timer = try Timer.start(); + const start = timer.lap(); while (offset < BytesToHash) : (offset += block.len) { h.update(block[0..]); } - const end = c.clock(); + const end = timer.read(); - const elapsed_s = f64((end - start) * c.CLOCKS_PER_SEC) / 1000000; - const throughput = u64(BytesToHash / elapsed_s); + const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s; + const throughput = @floatToInt(u64, BytesToHash / elapsed_s); - try stdout.print("{}: ", @typeName(HashFunction)); - try stdout.print("{} Mb/s\n", throughput); + try stdout.print("{}: {} MiB/s\n", @typeName(HashFunction), throughput / (1 * MiB)); } |
