| ... | @@ -1,87 +1,97 @@ | ... | @@ -1,87 +1,97 @@ |
| | 1 | //! Secure Hashing Algorithm 2 (SHA2) |
| | 2 | //! |
| | 3 | //! Published by the National Institue of Standards and Technology (NIST) [1] [2]. |
| | 4 | //! |
| | 5 | //! Truncation mitigates length-extension attacks but increases vulnerability to collision |
| | 6 | //! attacks. Collision attacks remain impractical for all types defined here. |
| | 7 | //! |
| | 8 | //! T: original hash function, whose output is simply truncated. |
| | 9 | //! A truncated output is just the first bytes of a longer output. |
| | 10 | //! _: hash function with context separation. |
| | 11 | //! Different lengths produce completely different outputs. |
| | 12 | //! |
| | 13 | //! [1] https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf |
| | 14 | //! [2] https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf |
| | 15 | |
| 1 | const std = @import("../std.zig"); | 16 | const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | 17 | const builtin = @import("builtin"); |
| 3 | const mem = std.mem; | 18 | const mem = std.mem; |
| 4 | const math = std.math; | 19 | const math = std.math; |
| 5 | const htest = @import("test.zig"); | 20 | const htest = @import("test.zig"); |
| 6 | | 21 | |
| 7 | ///////////////////// | 22 | pub const Sha224 = Sha2x32(iv224, 224); |
| 8 | // Sha224 + Sha256 | 23 | pub const Sha256 = Sha2x32(iv256, 256); |
| 9 | | 24 | pub const Sha384 = Sha2x64(iv384, 384); |
| 10 | const RoundParam256 = struct { | 25 | pub const Sha512 = Sha2x64(iv512, 512); |
| 11 | a: usize, | 26 | |
| 12 | b: usize, | 27 | /// SHA-256 truncated to leftmost 192 bits. |
| 13 | c: usize, | 28 | pub const Sha256T192 = Sha2x32(iv256, 192); |
| 14 | d: usize, | 29 | |
| 15 | e: usize, | 30 | /// SHA-512 truncated to leftmost 224 bits. |
| 16 | f: usize, | 31 | pub const Sha512T224 = Sha2x64(iv512, 224); |
| 17 | g: usize, | 32 | /// SHA-512 truncated to leftmost 256 bits. |
| 18 | h: usize, | 33 | pub const Sha512T256 = Sha2x64(iv512, 256); |
| 19 | i: usize, | 34 | |
| | 35 | /// SHA-512 with a different initialization vector truncated to leftmost 224 bits. |
| | 36 | pub const Sha512_224 = Sha2x64(truncatedSha512Iv(224), 224); |
| | 37 | /// SHA-512 with a different initialization vector truncated to leftmost 256 bits. |
| | 38 | pub const Sha512_256 = Sha2x64(truncatedSha512Iv(256), 256); |
| | 39 | |
| | 40 | /// Low 32 bits of iv384. |
| | 41 | const iv224 = Iv32{ |
| | 42 | 0xC1059ED8, |
| | 43 | 0x367CD507, |
| | 44 | 0x3070DD17, |
| | 45 | 0xF70E5939, |
| | 46 | 0xFFC00B31, |
| | 47 | 0x68581511, |
| | 48 | 0x64F98FA7, |
| | 49 | 0xBEFA4FA4, |
| 20 | }; | 50 | }; |
| 21 | | 51 | /// First thirty-two bits of the fractional parts of the square |
| 22 | fn roundParam256(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize) RoundParam256 { | 52 | /// roots of the first eight prime numbers. |
| 23 | return RoundParam256{ | 53 | const iv256 = Iv32{ |
| 24 | .a = a, | 54 | 0x6A09E667, |
| 25 | .b = b, | 55 | 0xBB67AE85, |
| 26 | .c = c, | 56 | 0x3C6EF372, |
| 27 | .d = d, | 57 | 0xA54FF53A, |
| 28 | .e = e, | 58 | 0x510E527F, |
| 29 | .f = f, | 59 | 0x9B05688C, |
| 30 | .g = g, | 60 | 0x1F83D9AB, |
| 31 | .h = h, | 61 | 0x5BE0CD19, |
| 32 | .i = i, | | |
| 33 | }; | | |
| 34 | } | | |
| 35 | | | |
| 36 | const Sha2Params32 = struct { | | |
| 37 | iv0: u32, | | |
| 38 | iv1: u32, | | |
| 39 | iv2: u32, | | |
| 40 | iv3: u32, | | |
| 41 | iv4: u32, | | |
| 42 | iv5: u32, | | |
| 43 | iv6: u32, | | |
| 44 | iv7: u32, | | |
| 45 | digest_bits: usize, | | |
| 46 | }; | 62 | }; |
| 47 | | 63 | |
| 48 | const Sha224Params = Sha2Params32{ | 64 | /// First sixty-four bits of the fractional parts of the square |
| 49 | .iv0 = 0xC1059ED8, | 65 | /// roots of the ninth through sixteenth prime numbers. |
| 50 | .iv1 = 0x367CD507, | 66 | const iv384 = Iv64{ |
| 51 | .iv2 = 0x3070DD17, | 67 | 0xCBBB9D5DC1059ED8, |
| 52 | .iv3 = 0xF70E5939, | 68 | 0x629A292A367CD507, |
| 53 | .iv4 = 0xFFC00B31, | 69 | 0x9159015A3070DD17, |
| 54 | .iv5 = 0x68581511, | 70 | 0x152FECD8F70E5939, |
| 55 | .iv6 = 0x64F98FA7, | 71 | 0x67332667FFC00B31, |
| 56 | .iv7 = 0xBEFA4FA4, | 72 | 0x8EB44A8768581511, |
| 57 | .digest_bits = 224, | 73 | 0xDB0C2E0D64F98FA7, |
| | 74 | 0x47B5481DBEFA4FA4, |
| 58 | }; | 75 | }; |
| 59 | | 76 | /// First sixty-four bits of the fractional parts of the square |
| 60 | const Sha256Params = Sha2Params32{ | 77 | /// roots of the first eight prime numbers. |
| 61 | .iv0 = 0x6A09E667, | 78 | const iv512 = Iv64{ |
| 62 | .iv1 = 0xBB67AE85, | 79 | 0x6A09E667F3BCC908, |
| 63 | .iv2 = 0x3C6EF372, | 80 | 0xBB67AE8584CAA73B, |
| 64 | .iv3 = 0xA54FF53A, | 81 | 0x3C6EF372FE94F82B, |
| 65 | .iv4 = 0x510E527F, | 82 | 0xA54FF53A5F1D36F1, |
| 66 | .iv5 = 0x9B05688C, | 83 | 0x510E527FADE682D1, |
| 67 | .iv6 = 0x1F83D9AB, | 84 | 0x9B05688C2B3E6C1F, |
| 68 | .iv7 = 0x5BE0CD19, | 85 | 0x1F83D9ABFB41BD6B, |
| 69 | .digest_bits = 256, | 86 | 0x5BE0CD19137E2179, |
| 70 | }; | 87 | }; |
| 71 | | 88 | |
| 72 | const v4u32 = @Vector(4, u32); | 89 | const Iv32 = [8]u32; |
| 73 | | 90 | fn Sha2x32(comptime iv: Iv32, digest_bits: comptime_int) type { |
| 74 | /// SHA-224 | | |
| 75 | pub const Sha224 = Sha2x32(Sha224Params); | | |
| 76 | | | |
| 77 | /// SHA-256 | | |
| 78 | pub const Sha256 = Sha2x32(Sha256Params); | | |
| 79 | | | |
| 80 | fn Sha2x32(comptime params: Sha2Params32) type { | | |
| 81 | return struct { | 91 | return struct { |
| 82 | const Self = @This(); | 92 | const Self = @This(); |
| 83 | pub const block_length = 64; | 93 | pub const block_length = 64; |
| 84 | pub const digest_length = params.digest_bits / 8; | 94 | pub const digest_length = digest_bits / 8; |
| 85 | pub const Options = struct {}; | 95 | pub const Options = struct {}; |
| 86 | | 96 | |
| 87 | s: [8]u32 align(16), | 97 | s: [8]u32 align(16), |
| ... | @@ -92,18 +102,7 @@ fn Sha2x32(comptime params: Sha2Params32) type { | ... | @@ -92,18 +102,7 @@ fn Sha2x32(comptime params: Sha2Params32) type { |
| 92 | | 102 | |
| 93 | pub fn init(options: Options) Self { | 103 | pub fn init(options: Options) Self { |
| 94 | _ = options; | 104 | _ = options; |
| 95 | return Self{ | 105 | return Self{ .s = iv }; |
| 96 | .s = [_]u32{ | | |
| 97 | params.iv0, | | |
| 98 | params.iv1, | | |
| 99 | params.iv2, | | |
| 100 | params.iv3, | | |
| 101 | params.iv4, | | |
| 102 | params.iv5, | | |
| 103 | params.iv6, | | |
| 104 | params.iv7, | | |
| 105 | }, | | |
| 106 | }; | | |
| 107 | } | 106 | } |
| 108 | | 107 | |
| 109 | pub fn hash(b: []const u8, out: *[digest_length]u8, options: Options) void { | 108 | pub fn hash(b: []const u8, out: *[digest_length]u8, options: Options) void { |
| ... | @@ -167,8 +166,8 @@ fn Sha2x32(comptime params: Sha2Params32) type { | ... | @@ -167,8 +166,8 @@ fn Sha2x32(comptime params: Sha2Params32) type { |
| 167 | | 166 | |
| 168 | d.round(&d.buf); | 167 | d.round(&d.buf); |
| 169 | | 168 | |
| 170 | // May truncate for possible 224 output | 169 | // May truncate for possible 224 or 192 output |
| 171 | const rr = d.s[0 .. params.digest_bits / 32]; | 170 | const rr = d.s[0 .. digest_length / 4]; |
| 172 | | 171 | |
| 173 | for (rr, 0..) |s, j| { | 172 | for (rr, 0..) |s, j| { |
| 174 | mem.writeInt(u32, out[4 * j ..][0..4], s, .big); | 173 | mem.writeInt(u32, out[4 * j ..][0..4], s, .big); |
| ... | @@ -199,11 +198,12 @@ fn Sha2x32(comptime params: Sha2Params32) type { | ... | @@ -199,11 +198,12 @@ fn Sha2x32(comptime params: Sha2Params32) type { |
| 199 | } | 198 | } |
| 200 | | 199 | |
| 201 | if (!@inComptime()) { | 200 | if (!@inComptime()) { |
| | 201 | const V4u32 = @Vector(4, u32); |
| 202 | switch (builtin.cpu.arch) { | 202 | switch (builtin.cpu.arch) { |
| 203 | .aarch64 => if (builtin.zig_backend != .stage2_c and comptime std.Target.aarch64.featureSetHas(builtin.cpu.features, .sha2)) { | 203 | .aarch64 => if (builtin.zig_backend != .stage2_c and comptime std.Target.aarch64.featureSetHas(builtin.cpu.features, .sha2)) { |
| 204 | var x: v4u32 = d.s[0..4].*; | 204 | var x: V4u32 = d.s[0..4].*; |
| 205 | var y: v4u32 = d.s[4..8].*; | 205 | var y: V4u32 = d.s[4..8].*; |
| 206 | const s_v = @as(*[16]v4u32, @ptrCast(&s)); | 206 | const s_v = @as(*[16]V4u32, @ptrCast(&s)); |
| 207 | | 207 | |
| 208 | comptime var k: u8 = 0; | 208 | comptime var k: u8 = 0; |
| 209 | inline while (k < 16) : (k += 1) { | 209 | inline while (k < 16) : (k += 1) { |
| ... | @@ -211,7 +211,7 @@ fn Sha2x32(comptime params: Sha2Params32) type { | ... | @@ -211,7 +211,7 @@ fn Sha2x32(comptime params: Sha2Params32) type { |
| 211 | s_v[k] = asm ( | 211 | s_v[k] = asm ( |
| 212 | \\sha256su0.4s %[w0_3], %[w4_7] | 212 | \\sha256su0.4s %[w0_3], %[w4_7] |
| 213 | \\sha256su1.4s %[w0_3], %[w8_11], %[w12_15] | 213 | \\sha256su1.4s %[w0_3], %[w8_11], %[w12_15] |
| 214 | : [w0_3] "=w" (-> v4u32), | 214 | : [w0_3] "=w" (-> V4u32), |
| 215 | : [_] "0" (s_v[k - 4]), | 215 | : [_] "0" (s_v[k - 4]), |
| 216 | [w4_7] "w" (s_v[k - 3]), | 216 | [w4_7] "w" (s_v[k - 3]), |
| 217 | [w8_11] "w" (s_v[k - 2]), | 217 | [w8_11] "w" (s_v[k - 2]), |
| ... | @@ -219,7 +219,7 @@ fn Sha2x32(comptime params: Sha2Params32) type { | ... | @@ -219,7 +219,7 @@ fn Sha2x32(comptime params: Sha2Params32) type { |
| 219 | ); | 219 | ); |
| 220 | } | 220 | } |
| 221 | | 221 | |
| 222 | const w: v4u32 = s_v[k] +% @as(v4u32, W[4 * k ..][0..4].*); | 222 | const w: V4u32 = s_v[k] +% @as(V4u32, W[4 * k ..][0..4].*); |
| 223 | asm volatile ( | 223 | asm volatile ( |
| 224 | \\mov.4s v0, %[x] | 224 | \\mov.4s v0, %[x] |
| 225 | \\sha256h.4s %[x], %[y], %[w] | 225 | \\sha256h.4s %[x], %[y], %[w] |
| ... | @@ -233,15 +233,15 @@ fn Sha2x32(comptime params: Sha2Params32) type { | ... | @@ -233,15 +233,15 @@ fn Sha2x32(comptime params: Sha2Params32) type { |
| 233 | ); | 233 | ); |
| 234 | } | 234 | } |
| 235 | | 235 | |
| 236 | d.s[0..4].* = x +% @as(v4u32, d.s[0..4].*); | 236 | d.s[0..4].* = x +% @as(V4u32, d.s[0..4].*); |
| 237 | d.s[4..8].* = y +% @as(v4u32, d.s[4..8].*); | 237 | d.s[4..8].* = y +% @as(V4u32, d.s[4..8].*); |
| 238 | return; | 238 | return; |
| 239 | }, | 239 | }, |
| 240 | // C backend doesn't currently support passing vectors to inline asm. | 240 | // C backend doesn't currently support passing vectors to inline asm. |
| 241 | .x86_64 => if (builtin.zig_backend != .stage2_c and comptime std.Target.x86.featureSetHasAll(builtin.cpu.features, .{ .sha, .avx2 })) { | 241 | .x86_64 => if (builtin.zig_backend != .stage2_c and comptime std.Target.x86.featureSetHasAll(builtin.cpu.features, .{ .sha, .avx2 })) { |
| 242 | var x: v4u32 = [_]u32{ d.s[5], d.s[4], d.s[1], d.s[0] }; | 242 | var x: V4u32 = [_]u32{ d.s[5], d.s[4], d.s[1], d.s[0] }; |
| 243 | var y: v4u32 = [_]u32{ d.s[7], d.s[6], d.s[3], d.s[2] }; | 243 | var y: V4u32 = [_]u32{ d.s[7], d.s[6], d.s[3], d.s[2] }; |
| 244 | const s_v = @as(*[16]v4u32, @ptrCast(&s)); | 244 | const s_v = @as(*[16]V4u32, @ptrCast(&s)); |
| 245 | | 245 | |
| 246 | comptime var k: u8 = 0; | 246 | comptime var k: u8 = 0; |
| 247 | inline while (k < 16) : (k += 1) { | 247 | inline while (k < 16) : (k += 1) { |
| ... | @@ -253,7 +253,7 @@ fn Sha2x32(comptime params: Sha2Params32) type { | ... | @@ -253,7 +253,7 @@ fn Sha2x32(comptime params: Sha2Params32) type { |
| 253 | \\ paddd %[tmp], %[result] | 253 | \\ paddd %[tmp], %[result] |
| 254 | \\ sha256msg2 %[w12_15], %[result] | 254 | \\ sha256msg2 %[w12_15], %[result] |
| 255 | : [tmp] "=&x" (tmp), | 255 | : [tmp] "=&x" (tmp), |
| 256 | [result] "=&x" (-> v4u32), | 256 | [result] "=&x" (-> V4u32), |
| 257 | : [_] "0" (tmp), | 257 | : [_] "0" (tmp), |
| 258 | [w4_7] "x" (s_v[k + 1]), | 258 | [w4_7] "x" (s_v[k + 1]), |
| 259 | [w8_11] "x" (s_v[k + 2]), | 259 | [w8_11] "x" (s_v[k + 2]), |
| ... | @@ -261,19 +261,19 @@ fn Sha2x32(comptime params: Sha2Params32) type { | ... | @@ -261,19 +261,19 @@ fn Sha2x32(comptime params: Sha2Params32) type { |
| 261 | ); | 261 | ); |
| 262 | } | 262 | } |
| 263 | | 263 | |
| 264 | const w: v4u32 = s_v[k] +% @as(v4u32, W[4 * k ..][0..4].*); | 264 | const w: V4u32 = s_v[k] +% @as(V4u32, W[4 * k ..][0..4].*); |
| 265 | y = asm ("sha256rnds2 %[x], %[y]" | 265 | y = asm ("sha256rnds2 %[x], %[y]" |
| 266 | : [y] "=x" (-> v4u32), | 266 | : [y] "=x" (-> V4u32), |
| 267 | : [_] "0" (y), | 267 | : [_] "0" (y), |
| 268 | [x] "x" (x), | 268 | [x] "x" (x), |
| 269 | [_] "{xmm0}" (w), | 269 | [_] "{xmm0}" (w), |
| 270 | ); | 270 | ); |
| 271 | | 271 | |
| 272 | x = asm ("sha256rnds2 %[y], %[x]" | 272 | x = asm ("sha256rnds2 %[y], %[x]" |
| 273 | : [x] "=x" (-> v4u32), | 273 | : [x] "=x" (-> V4u32), |
| 274 | : [_] "0" (x), | 274 | : [_] "0" (x), |
| 275 | [y] "x" (y), | 275 | [y] "x" (y), |
| 276 | [_] "{xmm0}" (@as(v4u32, @bitCast(@as(u128, @bitCast(w)) >> 64))), | 276 | [_] "{xmm0}" (@as(V4u32, @bitCast(@as(u128, @bitCast(w)) >> 64))), |
| 277 | ); | 277 | ); |
| 278 | } | 278 | } |
| 279 | | 279 | |
| ... | @@ -296,16 +296,7 @@ fn Sha2x32(comptime params: Sha2Params32) type { | ... | @@ -296,16 +296,7 @@ fn Sha2x32(comptime params: Sha2Params32) type { |
| 296 | s[i] = s[i - 16] +% s[i - 7] +% (math.rotr(u32, s[i - 15], @as(u32, 7)) ^ math.rotr(u32, s[i - 15], @as(u32, 18)) ^ (s[i - 15] >> 3)) +% (math.rotr(u32, s[i - 2], @as(u32, 17)) ^ math.rotr(u32, s[i - 2], @as(u32, 19)) ^ (s[i - 2] >> 10)); | 296 | s[i] = s[i - 16] +% s[i - 7] +% (math.rotr(u32, s[i - 15], @as(u32, 7)) ^ math.rotr(u32, s[i - 15], @as(u32, 18)) ^ (s[i - 15] >> 3)) +% (math.rotr(u32, s[i - 2], @as(u32, 17)) ^ math.rotr(u32, s[i - 2], @as(u32, 19)) ^ (s[i - 2] >> 10)); |
| 297 | } | 297 | } |
| 298 | | 298 | |
| 299 | var v: [8]u32 = [_]u32{ | 299 | var v: [8]u32 = d.s; |
| 300 | d.s[0], | | |
| 301 | d.s[1], | | |
| 302 | d.s[2], | | |
| 303 | d.s[3], | | |
| 304 | d.s[4], | | |
| 305 | d.s[5], | | |
| 306 | d.s[6], | | |
| 307 | d.s[7], | | |
| 308 | }; | | |
| 309 | | 300 | |
| 310 | const round0 = comptime [_]RoundParam256{ | 301 | const round0 = comptime [_]RoundParam256{ |
| 311 | roundParam256(0, 1, 2, 3, 4, 5, 6, 7, 0), | 302 | roundParam256(0, 1, 2, 3, 4, 5, 6, 7, 0), |
| ... | @@ -381,14 +372,7 @@ fn Sha2x32(comptime params: Sha2Params32) type { | ... | @@ -381,14 +372,7 @@ fn Sha2x32(comptime params: Sha2Params32) type { |
| 381 | v[r.h] = v[r.h] +% (math.rotr(u32, v[r.a], @as(u32, 2)) ^ math.rotr(u32, v[r.a], @as(u32, 13)) ^ math.rotr(u32, v[r.a], @as(u32, 22))) +% ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c])); | 372 | v[r.h] = v[r.h] +% (math.rotr(u32, v[r.a], @as(u32, 2)) ^ math.rotr(u32, v[r.a], @as(u32, 13)) ^ math.rotr(u32, v[r.a], @as(u32, 22))) +% ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c])); |
| 382 | } | 373 | } |
| 383 | | 374 | |
| 384 | d.s[0] +%= v[0]; | 375 | for (&d.s, v) |*dv, vv| dv.* +%= vv; |
| 385 | d.s[1] +%= v[1]; | | |
| 386 | d.s[2] +%= v[2]; | | |
| 387 | d.s[3] +%= v[3]; | | |
| 388 | d.s[4] +%= v[4]; | | |
| 389 | d.s[5] +%= v[5]; | | |
| 390 | d.s[6] +%= v[6]; | | |
| 391 | d.s[7] +%= v[7]; | | |
| 392 | } | 376 | } |
| 393 | | 377 | |
| 394 | pub const Error = error{}; | 378 | pub const Error = error{}; |
| ... | @@ -405,7 +389,33 @@ fn Sha2x32(comptime params: Sha2Params32) type { | ... | @@ -405,7 +389,33 @@ fn Sha2x32(comptime params: Sha2Params32) type { |
| 405 | }; | 389 | }; |
| 406 | } | 390 | } |
| 407 | | 391 | |
| 408 | test "sha224 single" { | 392 | const RoundParam256 = struct { |
| | 393 | a: usize, |
| | 394 | b: usize, |
| | 395 | c: usize, |
| | 396 | d: usize, |
| | 397 | e: usize, |
| | 398 | f: usize, |
| | 399 | g: usize, |
| | 400 | h: usize, |
| | 401 | i: usize, |
| | 402 | }; |
| | 403 | |
| | 404 | fn roundParam256(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize) RoundParam256 { |
| | 405 | return RoundParam256{ |
| | 406 | .a = a, |
| | 407 | .b = b, |
| | 408 | .c = c, |
| | 409 | .d = d, |
| | 410 | .e = e, |
| | 411 | .f = f, |
| | 412 | .g = g, |
| | 413 | .h = h, |
| | 414 | .i = i, |
| | 415 | }; |
| | 416 | } |
| | 417 | |
| | 418 | test Sha224 { |
| 409 | try htest.assertEqualHash(Sha224, "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", ""); | 419 | try htest.assertEqualHash(Sha224, "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", ""); |
| 410 | try htest.assertEqualHash(Sha224, "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", "abc"); | 420 | try htest.assertEqualHash(Sha224, "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", "abc"); |
| 411 | try htest.assertEqualHash(Sha224, "c97ca9a559850ce97a04a96def6d99a9e0e0e2ab14e6b8df265fc0b3", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); | 421 | try htest.assertEqualHash(Sha224, "c97ca9a559850ce97a04a96def6d99a9e0e0e2ab14e6b8df265fc0b3", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); |
| ... | @@ -431,12 +441,18 @@ test "sha224 streaming" { | ... | @@ -431,12 +441,18 @@ test "sha224 streaming" { |
| 431 | try htest.assertEqual("23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", out[0..]); | 441 | try htest.assertEqual("23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", out[0..]); |
| 432 | } | 442 | } |
| 433 | | 443 | |
| 434 | test "sha256 single" { | 444 | test Sha256 { |
| 435 | try htest.assertEqualHash(Sha256, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""); | 445 | try htest.assertEqualHash(Sha256, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""); |
| 436 | try htest.assertEqualHash(Sha256, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", "abc"); | 446 | try htest.assertEqualHash(Sha256, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", "abc"); |
| 437 | try htest.assertEqualHash(Sha256, "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); | 447 | try htest.assertEqualHash(Sha256, "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); |
| 438 | } | 448 | } |
| 439 | | 449 | |
| | 450 | test Sha256T192 { |
| | 451 | try htest.assertEqualHash(Sha256T192, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934c", ""); |
| | 452 | try htest.assertEqualHash(Sha256T192, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9c", "abc"); |
| | 453 | try htest.assertEqualHash(Sha256T192, "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); |
| | 454 | } |
| | 455 | |
| 440 | test "sha256 streaming" { | 456 | test "sha256 streaming" { |
| 441 | var h = Sha256.init(.{}); | 457 | var h = Sha256.init(.{}); |
| 442 | var out: [32]u8 = undefined; | 458 | var out: [32]u8 = undefined; |
| ... | @@ -466,132 +482,15 @@ test "sha256 aligned final" { | ... | @@ -466,132 +482,15 @@ test "sha256 aligned final" { |
| 466 | h.final(out[0..]); | 482 | h.final(out[0..]); |
| 467 | } | 483 | } |
| 468 | | 484 | |
| 469 | ///////////////////// | 485 | const Iv64 = [8]u64; |
| 470 | // Sha384 + Sha512 | 486 | fn Sha2x64(comptime iv: Iv64, digest_bits: comptime_int) type { |
| 471 | | | |
| 472 | const RoundParam512 = struct { | | |
| 473 | a: usize, | | |
| 474 | b: usize, | | |
| 475 | c: usize, | | |
| 476 | d: usize, | | |
| 477 | e: usize, | | |
| 478 | f: usize, | | |
| 479 | g: usize, | | |
| 480 | h: usize, | | |
| 481 | i: usize, | | |
| 482 | k: u64, | | |
| 483 | }; | | |
| 484 | | | |
| 485 | fn roundParam512(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u64) RoundParam512 { | | |
| 486 | return RoundParam512{ | | |
| 487 | .a = a, | | |
| 488 | .b = b, | | |
| 489 | .c = c, | | |
| 490 | .d = d, | | |
| 491 | .e = e, | | |
| 492 | .f = f, | | |
| 493 | .g = g, | | |
| 494 | .h = h, | | |
| 495 | .i = i, | | |
| 496 | .k = k, | | |
| 497 | }; | | |
| 498 | } | | |
| 499 | | | |
| 500 | const Sha2Params64 = struct { | | |
| 501 | iv0: u64, | | |
| 502 | iv1: u64, | | |
| 503 | iv2: u64, | | |
| 504 | iv3: u64, | | |
| 505 | iv4: u64, | | |
| 506 | iv5: u64, | | |
| 507 | iv6: u64, | | |
| 508 | iv7: u64, | | |
| 509 | digest_bits: usize, | | |
| 510 | }; | | |
| 511 | | | |
| 512 | const Sha384Params = Sha2Params64{ | | |
| 513 | .iv0 = 0xCBBB9D5DC1059ED8, | | |
| 514 | .iv1 = 0x629A292A367CD507, | | |
| 515 | .iv2 = 0x9159015A3070DD17, | | |
| 516 | .iv3 = 0x152FECD8F70E5939, | | |
| 517 | .iv4 = 0x67332667FFC00B31, | | |
| 518 | .iv5 = 0x8EB44A8768581511, | | |
| 519 | .iv6 = 0xDB0C2E0D64F98FA7, | | |
| 520 | .iv7 = 0x47B5481DBEFA4FA4, | | |
| 521 | .digest_bits = 384, | | |
| 522 | }; | | |
| 523 | | | |
| 524 | const Sha512Params = Sha2Params64{ | | |
| 525 | .iv0 = 0x6A09E667F3BCC908, | | |
| 526 | .iv1 = 0xBB67AE8584CAA73B, | | |
| 527 | .iv2 = 0x3C6EF372FE94F82B, | | |
| 528 | .iv3 = 0xA54FF53A5F1D36F1, | | |
| 529 | .iv4 = 0x510E527FADE682D1, | | |
| 530 | .iv5 = 0x9B05688C2B3E6C1F, | | |
| 531 | .iv6 = 0x1F83D9ABFB41BD6B, | | |
| 532 | .iv7 = 0x5BE0CD19137E2179, | | |
| 533 | .digest_bits = 512, | | |
| 534 | }; | | |
| 535 | | | |
| 536 | const Sha512224Params = Sha2Params64{ | | |
| 537 | .iv0 = 0x8C3D37C819544DA2, | | |
| 538 | .iv1 = 0x73E1996689DCD4D6, | | |
| 539 | .iv2 = 0x1DFAB7AE32FF9C82, | | |
| 540 | .iv3 = 0x679DD514582F9FCF, | | |
| 541 | .iv4 = 0x0F6D2B697BD44DA8, | | |
| 542 | .iv5 = 0x77E36F7304C48942, | | |
| 543 | .iv6 = 0x3F9D85A86A1D36C8, | | |
| 544 | .iv7 = 0x1112E6AD91D692A1, | | |
| 545 | .digest_bits = 224, | | |
| 546 | }; | | |
| 547 | | | |
| 548 | const Sha512256Params = Sha2Params64{ | | |
| 549 | .iv0 = 0x22312194FC2BF72C, | | |
| 550 | .iv1 = 0x9F555FA3C84C64C2, | | |
| 551 | .iv2 = 0x2393B86B6F53B151, | | |
| 552 | .iv3 = 0x963877195940EABD, | | |
| 553 | .iv4 = 0x96283EE2A88EFFE3, | | |
| 554 | .iv5 = 0xBE5E1E2553863992, | | |
| 555 | .iv6 = 0x2B0199FC2C85B8AA, | | |
| 556 | .iv7 = 0x0EB72DDC81C52CA2, | | |
| 557 | .digest_bits = 256, | | |
| 558 | }; | | |
| 559 | | | |
| 560 | const Sha512T256Params = Sha2Params64{ | | |
| 561 | .iv0 = 0x6A09E667F3BCC908, | | |
| 562 | .iv1 = 0xBB67AE8584CAA73B, | | |
| 563 | .iv2 = 0x3C6EF372FE94F82B, | | |
| 564 | .iv3 = 0xA54FF53A5F1D36F1, | | |
| 565 | .iv4 = 0x510E527FADE682D1, | | |
| 566 | .iv5 = 0x9B05688C2B3E6C1F, | | |
| 567 | .iv6 = 0x1F83D9ABFB41BD6B, | | |
| 568 | .iv7 = 0x5BE0CD19137E2179, | | |
| 569 | .digest_bits = 256, | | |
| 570 | }; | | |
| 571 | | | |
| 572 | /// SHA-384 | | |
| 573 | pub const Sha384 = Sha2x64(Sha384Params); | | |
| 574 | | | |
| 575 | /// SHA-512 | | |
| 576 | pub const Sha512 = Sha2x64(Sha512Params); | | |
| 577 | | | |
| 578 | /// SHA-512/224 | | |
| 579 | pub const Sha512224 = Sha2x64(Sha512224Params); | | |
| 580 | | | |
| 581 | /// SHA-512/256 | | |
| 582 | pub const Sha512256 = Sha2x64(Sha512256Params); | | |
| 583 | | | |
| 584 | /// Truncated SHA-512 | | |
| 585 | pub const Sha512T256 = Sha2x64(Sha512T256Params); | | |
| 586 | | | |
| 587 | fn Sha2x64(comptime params: Sha2Params64) type { | | |
| 588 | return struct { | 487 | return struct { |
| 589 | const Self = @This(); | 488 | const Self = @This(); |
| 590 | pub const block_length = 128; | 489 | pub const block_length = 128; |
| 591 | pub const digest_length = params.digest_bits / 8; | 490 | pub const digest_length = std.math.divCeil(comptime_int, digest_bits, 8) catch unreachable; |
| 592 | pub const Options = struct {}; | 491 | pub const Options = struct {}; |
| 593 | | 492 | |
| 594 | s: [8]u64, | 493 | s: Iv64, |
| 595 | // Streaming Cache | 494 | // Streaming Cache |
| 596 | buf: [128]u8 = undefined, | 495 | buf: [128]u8 = undefined, |
| 597 | buf_len: u8 = 0, | 496 | buf_len: u8 = 0, |
| ... | @@ -599,18 +498,7 @@ fn Sha2x64(comptime params: Sha2Params64) type { | ... | @@ -599,18 +498,7 @@ fn Sha2x64(comptime params: Sha2Params64) type { |
| 599 | | 498 | |
| 600 | pub fn init(options: Options) Self { | 499 | pub fn init(options: Options) Self { |
| 601 | _ = options; | 500 | _ = options; |
| 602 | return Self{ | 501 | return Self{ .s = iv }; |
| 603 | .s = [_]u64{ | | |
| 604 | params.iv0, | | |
| 605 | params.iv1, | | |
| 606 | params.iv2, | | |
| 607 | params.iv3, | | |
| 608 | params.iv4, | | |
| 609 | params.iv5, | | |
| 610 | params.iv6, | | |
| 611 | params.iv7, | | |
| 612 | }, | | |
| 613 | }; | | |
| 614 | } | 502 | } |
| 615 | | 503 | |
| 616 | pub fn hash(b: []const u8, out: *[digest_length]u8, options: Options) void { | 504 | pub fn hash(b: []const u8, out: *[digest_length]u8, options: Options) void { |
| ... | @@ -675,18 +563,19 @@ fn Sha2x64(comptime params: Sha2Params64) type { | ... | @@ -675,18 +563,19 @@ fn Sha2x64(comptime params: Sha2Params64) type { |
| 675 | d.round(d.buf[0..]); | 563 | d.round(d.buf[0..]); |
| 676 | | 564 | |
| 677 | // May truncate for possible 384 output | 565 | // May truncate for possible 384 output |
| 678 | const rr = d.s[0 .. params.digest_bits / 64]; | 566 | const rr = d.s[0 .. digest_length / 8]; |
| 679 | | 567 | |
| 680 | for (rr, 0..) |s, j| { | 568 | for (rr, 0..) |s, j| { |
| 681 | mem.writeInt(u64, out[8 * j ..][0..8], s, .big); | 569 | mem.writeInt(u64, out[8 * j ..][0..8], s, .big); |
| 682 | } | 570 | } |
| 683 | | 571 | |
| 684 | const bytes_left = params.digest_bits / 8 % 8; | 572 | if (digest_bits % 8 != 0) @compileError("impl doesn't support non-byte digest_len"); |
| | 573 | const bytes_left = digest_bits / 8 % 8; |
| 685 | if (bytes_left > 0) { | 574 | if (bytes_left > 0) { |
| 686 | const rest = d.s[(params.digest_bits / 64)]; | 575 | const rest = d.s[(digest_bits / 64)]; |
| 687 | var buf: [8]u8 = undefined; | 576 | var buf: [8]u8 = undefined; |
| 688 | std.mem.writeInt(u64, &buf, rest, .big); | 577 | std.mem.writeInt(u64, &buf, rest, .big); |
| 689 | @memcpy(out[params.digest_bits / 64 * 8 ..], buf[0..bytes_left]); | 578 | @memcpy(out[digest_bits / 64 * 8 ..], buf[0..bytes_left]); |
| 690 | } | 579 | } |
| 691 | } | 580 | } |
| 692 | | 581 | |
| ... | @@ -709,16 +598,7 @@ fn Sha2x64(comptime params: Sha2Params64) type { | ... | @@ -709,16 +598,7 @@ fn Sha2x64(comptime params: Sha2Params64) type { |
| 709 | (math.rotr(u64, s[i - 2], @as(u64, 19)) ^ math.rotr(u64, s[i - 2], @as(u64, 61)) ^ (s[i - 2] >> 6)); | 598 | (math.rotr(u64, s[i - 2], @as(u64, 19)) ^ math.rotr(u64, s[i - 2], @as(u64, 61)) ^ (s[i - 2] >> 6)); |
| 710 | } | 599 | } |
| 711 | | 600 | |
| 712 | var v: [8]u64 = [_]u64{ | 601 | var v: [8]u64 = d.s; |
| 713 | d.s[0], | | |
| 714 | d.s[1], | | |
| 715 | d.s[2], | | |
| 716 | d.s[3], | | |
| 717 | d.s[4], | | |
| 718 | d.s[5], | | |
| 719 | d.s[6], | | |
| 720 | d.s[7], | | |
| 721 | }; | | |
| 722 | | 602 | |
| 723 | const round0 = comptime [_]RoundParam512{ | 603 | const round0 = comptime [_]RoundParam512{ |
| 724 | roundParam512(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98D728AE22), | 604 | roundParam512(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98D728AE22), |
| ... | @@ -810,19 +690,94 @@ fn Sha2x64(comptime params: Sha2Params64) type { | ... | @@ -810,19 +690,94 @@ fn Sha2x64(comptime params: Sha2Params64) type { |
| 810 | v[r.h] = v[r.h] +% (math.rotr(u64, v[r.a], @as(u64, 28)) ^ math.rotr(u64, v[r.a], @as(u64, 34)) ^ math.rotr(u64, v[r.a], @as(u64, 39))) +% ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c])); | 690 | v[r.h] = v[r.h] +% (math.rotr(u64, v[r.a], @as(u64, 28)) ^ math.rotr(u64, v[r.a], @as(u64, 34)) ^ math.rotr(u64, v[r.a], @as(u64, 39))) +% ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c])); |
| 811 | } | 691 | } |
| 812 | | 692 | |
| 813 | d.s[0] +%= v[0]; | 693 | for (&d.s, v) |*dv, vv| dv.* +%= vv; |
| 814 | d.s[1] +%= v[1]; | | |
| 815 | d.s[2] +%= v[2]; | | |
| 816 | d.s[3] +%= v[3]; | | |
| 817 | d.s[4] +%= v[4]; | | |
| 818 | d.s[5] +%= v[5]; | | |
| 819 | d.s[6] +%= v[6]; | | |
| 820 | d.s[7] +%= v[7]; | | |
| 821 | } | 694 | } |
| 822 | }; | 695 | }; |
| 823 | } | 696 | } |
| 824 | | 697 | |
| 825 | test "sha384 single" { | 698 | const RoundParam512 = struct { |
| | 699 | a: usize, |
| | 700 | b: usize, |
| | 701 | c: usize, |
| | 702 | d: usize, |
| | 703 | e: usize, |
| | 704 | f: usize, |
| | 705 | g: usize, |
| | 706 | h: usize, |
| | 707 | i: usize, |
| | 708 | k: u64, |
| | 709 | }; |
| | 710 | |
| | 711 | fn roundParam512(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u64) RoundParam512 { |
| | 712 | return RoundParam512{ |
| | 713 | .a = a, |
| | 714 | .b = b, |
| | 715 | .c = c, |
| | 716 | .d = d, |
| | 717 | .e = e, |
| | 718 | .f = f, |
| | 719 | .g = g, |
| | 720 | .h = h, |
| | 721 | .i = i, |
| | 722 | .k = k, |
| | 723 | }; |
| | 724 | } |
| | 725 | |
| | 726 | /// Compute the IV for a truncated version of SHA512 per FIPS 180 Section 5.3.6 |
| | 727 | fn truncatedSha512Iv(digest_len: comptime_int) Iv64 { |
| | 728 | const assert = std.debug.assert; |
| | 729 | comptime assert(digest_len > 1); |
| | 730 | comptime assert(digest_len <= 512); |
| | 731 | comptime assert(digest_len != 384); // NIST specially defines this (see `iv384`) |
| | 732 | |
| | 733 | comptime var gen_params = iv512; |
| | 734 | inline for (&gen_params) |*iv| { |
| | 735 | iv.* ^= 0xa5a5a5a5a5a5a5a5; |
| | 736 | } |
| | 737 | const GenHash = Sha2x64(gen_params, 512); |
| | 738 | |
| | 739 | var params: [@sizeOf(Iv64)]u8 = undefined; |
| | 740 | const algo_str = std.fmt.comptimePrint("SHA-512/{d}", .{digest_len}); |
| | 741 | GenHash.hash(algo_str, &params, .{}); |
| | 742 | |
| | 743 | return Iv64{ |
| | 744 | std.mem.readInt(u64, params[0..8], .big), |
| | 745 | std.mem.readInt(u64, params[8..16], .big), |
| | 746 | std.mem.readInt(u64, params[16..24], .big), |
| | 747 | std.mem.readInt(u64, params[24..32], .big), |
| | 748 | std.mem.readInt(u64, params[32..40], .big), |
| | 749 | std.mem.readInt(u64, params[40..48], .big), |
| | 750 | std.mem.readInt(u64, params[48..56], .big), |
| | 751 | std.mem.readInt(u64, params[56..64], .big), |
| | 752 | }; |
| | 753 | } |
| | 754 | |
| | 755 | test truncatedSha512Iv { |
| | 756 | // Section 5.3.6.1 |
| | 757 | try std.testing.expectEqual(Iv64{ |
| | 758 | 0x8C3D37C819544DA2, |
| | 759 | 0x73E1996689DCD4D6, |
| | 760 | 0x1DFAB7AE32FF9C82, |
| | 761 | 0x679DD514582F9FCF, |
| | 762 | 0x0F6D2B697BD44DA8, |
| | 763 | 0x77E36F7304C48942, |
| | 764 | 0x3F9D85A86A1D36C8, |
| | 765 | 0x1112E6AD91D692A1, |
| | 766 | }, truncatedSha512Iv(224)); |
| | 767 | // Section 5.3.6.2 |
| | 768 | try std.testing.expectEqual(Iv64{ |
| | 769 | 0x22312194FC2BF72C, |
| | 770 | 0x9F555FA3C84C64C2, |
| | 771 | 0x2393B86B6F53B151, |
| | 772 | 0x963877195940EABD, |
| | 773 | 0x96283EE2A88EFFE3, |
| | 774 | 0xBE5E1E2553863992, |
| | 775 | 0x2B0199FC2C85B8AA, |
| | 776 | 0x0EB72DDC81C52CA2, |
| | 777 | }, truncatedSha512Iv(256)); |
| | 778 | } |
| | 779 | |
| | 780 | test Sha384 { |
| 826 | const h1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"; | 781 | const h1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"; |
| 827 | try htest.assertEqualHash(Sha384, h1, ""); | 782 | try htest.assertEqualHash(Sha384, h1, ""); |
| 828 | | 783 | |
| ... | @@ -856,7 +811,7 @@ test "sha384 streaming" { | ... | @@ -856,7 +811,7 @@ test "sha384 streaming" { |
| 856 | try htest.assertEqual(h2, out[0..]); | 811 | try htest.assertEqual(h2, out[0..]); |
| 857 | } | 812 | } |
| 858 | | 813 | |
| 859 | test "sha512 single" { | 814 | test Sha512 { |
| 860 | const h1 = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"; | 815 | const h1 = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"; |
| 861 | try htest.assertEqualHash(Sha512, h1, ""); | 816 | try htest.assertEqualHash(Sha512, h1, ""); |
| 862 | | 817 | |
| ... | @@ -899,24 +854,24 @@ test "sha512 aligned final" { | ... | @@ -899,24 +854,24 @@ test "sha512 aligned final" { |
| 899 | h.final(out[0..]); | 854 | h.final(out[0..]); |
| 900 | } | 855 | } |
| 901 | | 856 | |
| 902 | test "sha512-224 single" { | 857 | test Sha512_224 { |
| 903 | const h1 = "6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4"; | 858 | const h1 = "6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4"; |
| 904 | try htest.assertEqualHash(Sha512224, h1, ""); | 859 | try htest.assertEqualHash(Sha512_224, h1, ""); |
| 905 | | 860 | |
| 906 | const h2 = "4634270f707b6a54daae7530460842e20e37ed265ceee9a43e8924aa"; | 861 | const h2 = "4634270f707b6a54daae7530460842e20e37ed265ceee9a43e8924aa"; |
| 907 | try htest.assertEqualHash(Sha512224, h2, "abc"); | 862 | try htest.assertEqualHash(Sha512_224, h2, "abc"); |
| 908 | | 863 | |
| 909 | const h3 = "23fec5bb94d60b23308192640b0c453335d664734fe40e7268674af9"; | 864 | const h3 = "23fec5bb94d60b23308192640b0c453335d664734fe40e7268674af9"; |
| 910 | try htest.assertEqualHash(Sha512224, h3, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); | 865 | try htest.assertEqualHash(Sha512_224, h3, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); |
| 911 | } | 866 | } |
| 912 | | 867 | |
| 913 | test "sha512-256 single" { | 868 | test Sha512_256 { |
| 914 | const h1 = "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a"; | 869 | const h1 = "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a"; |
| 915 | try htest.assertEqualHash(Sha512256, h1, ""); | 870 | try htest.assertEqualHash(Sha512_256, h1, ""); |
| 916 | | 871 | |
| 917 | const h2 = "53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"; | 872 | const h2 = "53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"; |
| 918 | try htest.assertEqualHash(Sha512256, h2, "abc"); | 873 | try htest.assertEqualHash(Sha512_256, h2, "abc"); |
| 919 | | 874 | |
| 920 | const h3 = "3928e184fb8690f840da3988121d31be65cb9d3ef83ee6146feac861e19b563a"; | 875 | const h3 = "3928e184fb8690f840da3988121d31be65cb9d3ef83ee6146feac861e19b563a"; |
| 921 | try htest.assertEqualHash(Sha512256, h3, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); | 876 | try htest.assertEqualHash(Sha512_256, h3, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); |
| 922 | } | 877 | } |