From 0d9547a3883be4641072cf27733b0412400e1834 Mon Sep 17 00:00:00 2001 From: Zack Puhl Date: Sat, 20 Dec 2025 13:39:12 -0500 Subject: [PATCH] Add RIPEMD Hashing to stdlb (#2663) * Add RIPE-MD Hashing to stdlib --------- Co-authored-by: Christoffer Lerno --- benchmarks/stdlib/hash/ripemd.c3 | 76 ++++ lib/std/hash/ripemd.c3 | 575 +++++++++++++++++++++++++++++++ releasenotes.md | 1 + test/unit/stdlib/hash/ripemd.c3 | 174 ++++++++++ 4 files changed, 826 insertions(+) create mode 100644 benchmarks/stdlib/hash/ripemd.c3 create mode 100644 lib/std/hash/ripemd.c3 create mode 100644 test/unit/stdlib/hash/ripemd.c3 diff --git a/benchmarks/stdlib/hash/ripemd.c3 b/benchmarks/stdlib/hash/ripemd.c3 new file mode 100644 index 000000000..987d38463 --- /dev/null +++ b/benchmarks/stdlib/hash/ripemd.c3 @@ -0,0 +1,76 @@ +// Copyright (c) 2025 Zack Puhl . All rights reserved. +// Use of this source code is governed by the MIT license +// a copy of which can be found in the LICENSE_STDLIB file. +module ripemd_bench; + +fn void initialize_bench() @init +{ + set_benchmark_warmup_iterations(3); + set_benchmark_max_iterations(256); + + input = mem::alloc_array(char, BUFSZ); + input[:BUFSZ] = (char[]){ [0..BUFSZ-1] = 0xA5 }[..]; + input_slice = input[:BUFSZ]; +} + +fn void teardown_bench() @finalizer +{ + mem::free(input); + input = null; +} + +char* input; +char[] input_slice; +const usz BUFSZ = 1024 * 1024; + +module ripemd_bench @benchmark; + +import std::hash; + +fn void ripemd_128() +{ + runtime::@start_benchmark(); + char[*] myset = ripemd::hash{128}(input_slice); + runtime::@end_benchmark(); + mem::zero_volatile(myset[..]); +} + +fn void ripemd_160() +{ + runtime::@start_benchmark(); + char[*] myset = ripemd::hash{160}(input_slice); + runtime::@end_benchmark(); + mem::zero_volatile(myset[..]); +} + +fn void ripemd_256() +{ + runtime::@start_benchmark(); + char[*] myset = ripemd::hash{256}(input_slice); + runtime::@end_benchmark(); + mem::zero_volatile(myset[..]); +} + +fn void ripemd_320() +{ + runtime::@start_benchmark(); + char[*] myset = ripemd::hash{320}(input_slice); + runtime::@end_benchmark(); + mem::zero_volatile(myset[..]); +} + +fn void compared_with_sha256() +{ + runtime::@start_benchmark(); + char[*] myset = sha256::hash(input_slice); + runtime::@end_benchmark(); + mem::zero_volatile(myset[..]); +} + +fn void compared_with_whirlpool() +{ + runtime::@start_benchmark(); + char[*] myset = whirlpool::hash(input_slice); + runtime::@end_benchmark(); + mem::zero_volatile(myset[..]); +} \ No newline at end of file diff --git a/lib/std/hash/ripemd.c3 b/lib/std/hash/ripemd.c3 new file mode 100644 index 000000000..376ec1cc6 --- /dev/null +++ b/lib/std/hash/ripemd.c3 @@ -0,0 +1,575 @@ +// Copyright (c) 2025 Zack Puhl . All rights reserved. +// Use of this source code is governed by the MIT license +// a copy of which can be found in the LICENSE_STDLIB file. +<* + @require @in(DIGEST_BITS, ...PERMISSIBLE_SIZES_BITS) : "Invalid DIGEST_BITS; must be one of {128, 160, 256, 320}." +*> +module std::hash::ripemd { DIGEST_BITS }; + + +<* Unchanging block size. *> +const BLOCK_SIZE = 64; + +const usz[4] PERMISSIBLE_SIZES_BITS = { 128, 160, 256, 320 }; + +<* RIPE-MD initial values. *> +const uint[10] H = { + 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0, + 0x76543210, 0xfedcba98, 0x89abcdef, 0x01234567, 0x3c2d1e0f +}; + +<* RIPE-MD constant values. *> +const uint[9] K = { + 0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e, + 0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9 +}; + +<* Ultimate digest's size in bytes. *> +const DIGEST_BYTES = DIGEST_BITS / 8; + + +struct RipeMd +{ + uint[10] state; + uint[16] buffer; + ulong byte_count; +} + + +<* + Compute the RIPE-MD hash of the given data. + + @param [in] data : "The data to hash." +*> +macro char[*] hash(char[] data) +{ + RipeMd r @noinit; + r.init(); + r.update(data); + return r.final(); +} + +<* + Initialize the RIPE-MD hash context. +*> +fn void RipeMd.init(&self) +{ + mem::zero_volatile(@as_char_view(*self)); + self.state[..] = H[..]; + // I don't care about the reason, I want to strangle whoever thought this was a good idea. + // I get it, you have to set the lane initializers correctly, but damn I want my hours back. + $if DIGEST_BITS == 256: self.state[4:4] = self.state[5:4]; $endif +} + +<* + Update the RIPE-MD hash context with the given data. + + @param [in] data : "The data to digest." +*> +fn void RipeMd.update(&self, char[] data) +{ + usz $bufsz = $sizeof(self.buffer); + uint avail = $bufsz - (uint)(self.byte_count & 0x3f); + self.byte_count += data.len; + + if (avail > data.len) + { + @as_char_view(self.buffer)[($bufsz - avail) : data.len] = data[..]; + return; + } + + @as_char_view(self.buffer)[($bufsz - avail) : avail] = data[:avail]; + self.transform(self.buffer); + data = data[avail..]; + + for (bool is_aligned = 0 == (usz)data.ptr % uint.sizeof; data.len >= $bufsz; data = data[$bufsz..]) + { + if (is_aligned) // when aligned, this optimization is a ~10-20% performance boost + { + self.transform(((uint*)data.ptr)[:$bufsz / uint.sizeof]); + } + else + { + @as_char_view(self.buffer)[:$bufsz] = data[:$bufsz]; + self.transform(self.buffer); + } + } + + @as_char_view(self.buffer)[:data.len] = data[..]; +} + +<* + Finalize the RIPE-MD hash context and return the final hash value. + This implicitly destroys the underlying hash structure for the sake of security. +*> +fn char[DIGEST_BYTES] RipeMd.final(&self) +{ + char[DIGEST_BYTES] result @align(uint.sizeof); + static char[64] padding = { [0] = 0x80, [1..63] = 0x00 }; + + // Napkin maffs. + ulong bits = (ulong)self.byte_count << 3; + uint index = (uint)self.byte_count & 0x3f; + uint padlen = (index < 56) ? (56 - index) : ((64 + 56) - index); + + // Update with padding, then append bit-length of digested message. + self.update(padding[:padlen]); + self.update(@as_char_view(bits)); + + // Clean up implicitly. + defer mem::zero_volatile(@as_char_view(*self)); + + // Copy and return. + ((uint*)&result)[:DIGEST_BYTES / uint.sizeof] = self.state[:DIGEST_BYTES / uint.sizeof]; + return result; +} + + +// State-based permutation functions given as a function pointer to each computation lane. +fn uint f1(uint x, uint y, uint z) @inline @local => x ^ y ^ z; +fn uint f2(uint x, uint y, uint z) @inline @local => z ^ (x & (y ^ z)); +fn uint f3(uint x, uint y, uint z) @inline @local => (x | ~y) ^ z; +fn uint f4(uint x, uint y, uint z) @inline @local => y ^ (z & (x ^ y)); +fn uint f5(uint x, uint y, uint z) @inline @local => x ^ (y | ~z); + +// The primary workhorse of the digest function. Behavior only changes slightly. +// All 128/256 inputs will expand with 'e' as 0 - they don't use it anyway. +macro @round(#a, b, #c, d, e, #func, k, x, s) @local +{ + #a += #func(b, #c, d) + x + k; + $switch: + $case DIGEST_BITS == 128 ||| DIGEST_BITS == 256: + #a = #a.rotl(s); + $case DIGEST_BITS == 160 ||| DIGEST_BITS == 320: + #a = #a.rotl(s) + e; + #c = #c.rotl(10); + $default: + $error "Invalid digest bits"; + $endswitch +} + +<* + Apply a transformation to some input data, but DO NOT inline the contents of the macro within the parent call. + + @param in : "Data or message block to process." +*> +fn void RipeMd.transform(&self, uint[BLOCK_SIZE / uint.sizeof] in) @noinline => self.@transform(in); + +<* + @param in : "Data or message block to process." +*> +macro RipeMd.@transform(&self, uint[BLOCK_SIZE / uint.sizeof] in) @local +{ + uint aa, bb, cc, dd, ee, aaa, bbb, ccc, ddd, eee; + uint[] state = self.state[..]; + + // Run computations lanes based on the size of the resulting digest. + // The behavior is different enough for each that this can simply stay broken out into separate cases. + // Otherwise, lacing them all together is just not worth the effort and isn't as clear to other developers. + // (No shade, but see 'RustCrypto/hashes' RIPE-MD macros for an example of what I mean...) + $switch DIGEST_BITS: + $case 128: + aa = state[0]; + bb = state[1]; + cc = state[2]; + dd = state[3]; + aaa = state[0]; + bbb = state[1]; + ccc = state[2]; + ddd = state[3]; + + @round(aa, bb, cc, dd, 0, f1, K[0], in[0], 11); @round(aaa, bbb, ccc, ddd, 0, f4, K[5], in[5], 8); + @round(dd, aa, bb, cc, 0, f1, K[0], in[1], 14); @round(ddd, aaa, bbb, ccc, 0, f4, K[5], in[14], 9); + @round(cc, dd, aa, bb, 0, f1, K[0], in[2], 15); @round(ccc, ddd, aaa, bbb, 0, f4, K[5], in[7], 9); + @round(bb, cc, dd, aa, 0, f1, K[0], in[3], 12); @round(bbb, ccc, ddd, aaa, 0, f4, K[5], in[0], 11); + @round(aa, bb, cc, dd, 0, f1, K[0], in[4], 5); @round(aaa, bbb, ccc, ddd, 0, f4, K[5], in[9], 13); + @round(dd, aa, bb, cc, 0, f1, K[0], in[5], 8); @round(ddd, aaa, bbb, ccc, 0, f4, K[5], in[2], 15); + @round(cc, dd, aa, bb, 0, f1, K[0], in[6], 7); @round(ccc, ddd, aaa, bbb, 0, f4, K[5], in[11], 15); + @round(bb, cc, dd, aa, 0, f1, K[0], in[7], 9); @round(bbb, ccc, ddd, aaa, 0, f4, K[5], in[4], 5); + @round(aa, bb, cc, dd, 0, f1, K[0], in[8], 11); @round(aaa, bbb, ccc, ddd, 0, f4, K[5], in[13], 7); + @round(dd, aa, bb, cc, 0, f1, K[0], in[9], 13); @round(ddd, aaa, bbb, ccc, 0, f4, K[5], in[6], 7); + @round(cc, dd, aa, bb, 0, f1, K[0], in[10], 14); @round(ccc, ddd, aaa, bbb, 0, f4, K[5], in[15], 8); + @round(bb, cc, dd, aa, 0, f1, K[0], in[11], 15); @round(bbb, ccc, ddd, aaa, 0, f4, K[5], in[8], 11); + @round(aa, bb, cc, dd, 0, f1, K[0], in[12], 6); @round(aaa, bbb, ccc, ddd, 0, f4, K[5], in[1], 14); + @round(dd, aa, bb, cc, 0, f1, K[0], in[13], 7); @round(ddd, aaa, bbb, ccc, 0, f4, K[5], in[10], 14); + @round(cc, dd, aa, bb, 0, f1, K[0], in[14], 9); @round(ccc, ddd, aaa, bbb, 0, f4, K[5], in[3], 12); + @round(bb, cc, dd, aa, 0, f1, K[0], in[15], 8); @round(bbb, ccc, ddd, aaa, 0, f4, K[5], in[12], 6); + + @round(aa, bb, cc, dd, 0, f2, K[1], in[7], 7); @round(aaa, bbb, ccc, ddd, 0, f3, K[6], in[6], 9); + @round(dd, aa, bb, cc, 0, f2, K[1], in[4], 6); @round(ddd, aaa, bbb, ccc, 0, f3, K[6], in[11], 13); + @round(cc, dd, aa, bb, 0, f2, K[1], in[13], 8); @round(ccc, ddd, aaa, bbb, 0, f3, K[6], in[3], 15); + @round(bb, cc, dd, aa, 0, f2, K[1], in[1], 13); @round(bbb, ccc, ddd, aaa, 0, f3, K[6], in[7], 7); + @round(aa, bb, cc, dd, 0, f2, K[1], in[10], 11); @round(aaa, bbb, ccc, ddd, 0, f3, K[6], in[0], 12); + @round(dd, aa, bb, cc, 0, f2, K[1], in[6], 9); @round(ddd, aaa, bbb, ccc, 0, f3, K[6], in[13], 8); + @round(cc, dd, aa, bb, 0, f2, K[1], in[15], 7); @round(ccc, ddd, aaa, bbb, 0, f3, K[6], in[5], 9); + @round(bb, cc, dd, aa, 0, f2, K[1], in[3], 15); @round(bbb, ccc, ddd, aaa, 0, f3, K[6], in[10], 11); + @round(aa, bb, cc, dd, 0, f2, K[1], in[12], 7); @round(aaa, bbb, ccc, ddd, 0, f3, K[6], in[14], 7); + @round(dd, aa, bb, cc, 0, f2, K[1], in[0], 12); @round(ddd, aaa, bbb, ccc, 0, f3, K[6], in[15], 7); + @round(cc, dd, aa, bb, 0, f2, K[1], in[9], 15); @round(ccc, ddd, aaa, bbb, 0, f3, K[6], in[8], 12); + @round(bb, cc, dd, aa, 0, f2, K[1], in[5], 9); @round(bbb, ccc, ddd, aaa, 0, f3, K[6], in[12], 7); + @round(aa, bb, cc, dd, 0, f2, K[1], in[2], 11); @round(aaa, bbb, ccc, ddd, 0, f3, K[6], in[4], 6); + @round(dd, aa, bb, cc, 0, f2, K[1], in[14], 7); @round(ddd, aaa, bbb, ccc, 0, f3, K[6], in[9], 15); + @round(cc, dd, aa, bb, 0, f2, K[1], in[11], 13); @round(ccc, ddd, aaa, bbb, 0, f3, K[6], in[1], 13); + @round(bb, cc, dd, aa, 0, f2, K[1], in[8], 12); @round(bbb, ccc, ddd, aaa, 0, f3, K[6], in[2], 11); + + @round(aa, bb, cc, dd, 0, f3, K[2], in[3], 11); @round(aaa, bbb, ccc, ddd, 0, f2, K[7], in[15], 9); + @round(dd, aa, bb, cc, 0, f3, K[2], in[10], 13); @round(ddd, aaa, bbb, ccc, 0, f2, K[7], in[5], 7); + @round(cc, dd, aa, bb, 0, f3, K[2], in[14], 6); @round(ccc, ddd, aaa, bbb, 0, f2, K[7], in[1], 15); + @round(bb, cc, dd, aa, 0, f3, K[2], in[4], 7); @round(bbb, ccc, ddd, aaa, 0, f2, K[7], in[3], 11); + @round(aa, bb, cc, dd, 0, f3, K[2], in[9], 14); @round(aaa, bbb, ccc, ddd, 0, f2, K[7], in[7], 8); + @round(dd, aa, bb, cc, 0, f3, K[2], in[15], 9); @round(ddd, aaa, bbb, ccc, 0, f2, K[7], in[14], 6); + @round(cc, dd, aa, bb, 0, f3, K[2], in[8], 13); @round(ccc, ddd, aaa, bbb, 0, f2, K[7], in[6], 6); + @round(bb, cc, dd, aa, 0, f3, K[2], in[1], 15); @round(bbb, ccc, ddd, aaa, 0, f2, K[7], in[9], 14); + @round(aa, bb, cc, dd, 0, f3, K[2], in[2], 14); @round(aaa, bbb, ccc, ddd, 0, f2, K[7], in[11], 12); + @round(dd, aa, bb, cc, 0, f3, K[2], in[7], 8); @round(ddd, aaa, bbb, ccc, 0, f2, K[7], in[8], 13); + @round(cc, dd, aa, bb, 0, f3, K[2], in[0], 13); @round(ccc, ddd, aaa, bbb, 0, f2, K[7], in[12], 5); + @round(bb, cc, dd, aa, 0, f3, K[2], in[6], 6); @round(bbb, ccc, ddd, aaa, 0, f2, K[7], in[2], 14); + @round(aa, bb, cc, dd, 0, f3, K[2], in[13], 5); @round(aaa, bbb, ccc, ddd, 0, f2, K[7], in[10], 13); + @round(dd, aa, bb, cc, 0, f3, K[2], in[11], 12); @round(ddd, aaa, bbb, ccc, 0, f2, K[7], in[0], 13); + @round(cc, dd, aa, bb, 0, f3, K[2], in[5], 7); @round(ccc, ddd, aaa, bbb, 0, f2, K[7], in[4], 7); + @round(bb, cc, dd, aa, 0, f3, K[2], in[12], 5); @round(bbb, ccc, ddd, aaa, 0, f2, K[7], in[13], 5); + + @round(aa, bb, cc, dd, 0, f4, K[3], in[1], 11); @round(aaa, bbb, ccc, ddd, 0, f1, 0, in[8], 15); + @round(dd, aa, bb, cc, 0, f4, K[3], in[9], 12); @round(ddd, aaa, bbb, ccc, 0, f1, 0, in[6], 5); + @round(cc, dd, aa, bb, 0, f4, K[3], in[11], 14); @round(ccc, ddd, aaa, bbb, 0, f1, 0, in[4], 8); + @round(bb, cc, dd, aa, 0, f4, K[3], in[10], 15); @round(bbb, ccc, ddd, aaa, 0, f1, 0, in[1], 11); + @round(aa, bb, cc, dd, 0, f4, K[3], in[0], 14); @round(aaa, bbb, ccc, ddd, 0, f1, 0, in[3], 14); + @round(dd, aa, bb, cc, 0, f4, K[3], in[8], 15); @round(ddd, aaa, bbb, ccc, 0, f1, 0, in[11], 14); + @round(cc, dd, aa, bb, 0, f4, K[3], in[12], 9); @round(ccc, ddd, aaa, bbb, 0, f1, 0, in[15], 6); + @round(bb, cc, dd, aa, 0, f4, K[3], in[4], 8); @round(bbb, ccc, ddd, aaa, 0, f1, 0, in[0], 14); + @round(aa, bb, cc, dd, 0, f4, K[3], in[13], 9); @round(aaa, bbb, ccc, ddd, 0, f1, 0, in[5], 6); + @round(dd, aa, bb, cc, 0, f4, K[3], in[3], 14); @round(ddd, aaa, bbb, ccc, 0, f1, 0, in[12], 9); + @round(cc, dd, aa, bb, 0, f4, K[3], in[7], 5); @round(ccc, ddd, aaa, bbb, 0, f1, 0, in[2], 12); + @round(bb, cc, dd, aa, 0, f4, K[3], in[15], 6); @round(bbb, ccc, ddd, aaa, 0, f1, 0, in[13], 9); + @round(aa, bb, cc, dd, 0, f4, K[3], in[14], 8); @round(aaa, bbb, ccc, ddd, 0, f1, 0, in[9], 12); + @round(dd, aa, bb, cc, 0, f4, K[3], in[5], 6); @round(ddd, aaa, bbb, ccc, 0, f1, 0, in[7], 5); + @round(cc, dd, aa, bb, 0, f4, K[3], in[6], 5); @round(ccc, ddd, aaa, bbb, 0, f1, 0, in[10], 15); + @round(bb, cc, dd, aa, 0, f4, K[3], in[2], 12); @round(bbb, ccc, ddd, aaa, 0, f1, 0, in[14], 8); + + ddd += cc + state[1]; + state[1] = state[2] + dd + aaa; + state[2] = state[3] + aa + bbb; + state[3] = state[0] + bb + ccc; + state[0] = ddd; + + $case 160: + aa = state[0]; + bb = state[1]; + cc = state[2]; + dd = state[3]; + ee = state[4]; + aaa = state[0]; + bbb = state[1]; + ccc = state[2]; + ddd = state[3]; + eee = state[4]; + + @round(aa, bb, cc, dd, ee, f1, K[0], in[0], 11); @round(aaa, bbb, ccc, ddd, eee, f5, K[5], in[5], 8); + @round(ee, aa, bb, cc, dd, f1, K[0], in[1], 14); @round(eee, aaa, bbb, ccc, ddd, f5, K[5], in[14], 9); + @round(dd, ee, aa, bb, cc, f1, K[0], in[2], 15); @round(ddd, eee, aaa, bbb, ccc, f5, K[5], in[7], 9); + @round(cc, dd, ee, aa, bb, f1, K[0], in[3], 12); @round(ccc, ddd, eee, aaa, bbb, f5, K[5], in[0], 11); + @round(bb, cc, dd, ee, aa, f1, K[0], in[4], 5); @round(bbb, ccc, ddd, eee, aaa, f5, K[5], in[9], 13); + @round(aa, bb, cc, dd, ee, f1, K[0], in[5], 8); @round(aaa, bbb, ccc, ddd, eee, f5, K[5], in[2], 15); + @round(ee, aa, bb, cc, dd, f1, K[0], in[6], 7); @round(eee, aaa, bbb, ccc, ddd, f5, K[5], in[11], 15); + @round(dd, ee, aa, bb, cc, f1, K[0], in[7], 9); @round(ddd, eee, aaa, bbb, ccc, f5, K[5], in[4], 5); + @round(cc, dd, ee, aa, bb, f1, K[0], in[8], 11); @round(ccc, ddd, eee, aaa, bbb, f5, K[5], in[13], 7); + @round(bb, cc, dd, ee, aa, f1, K[0], in[9], 13); @round(bbb, ccc, ddd, eee, aaa, f5, K[5], in[6], 7); + @round(aa, bb, cc, dd, ee, f1, K[0], in[10], 14); @round(aaa, bbb, ccc, ddd, eee, f5, K[5], in[15], 8); + @round(ee, aa, bb, cc, dd, f1, K[0], in[11], 15); @round(eee, aaa, bbb, ccc, ddd, f5, K[5], in[8], 11); + @round(dd, ee, aa, bb, cc, f1, K[0], in[12], 6); @round(ddd, eee, aaa, bbb, ccc, f5, K[5], in[1], 14); + @round(cc, dd, ee, aa, bb, f1, K[0], in[13], 7); @round(ccc, ddd, eee, aaa, bbb, f5, K[5], in[10], 14); + @round(bb, cc, dd, ee, aa, f1, K[0], in[14], 9); @round(bbb, ccc, ddd, eee, aaa, f5, K[5], in[3], 12); + @round(aa, bb, cc, dd, ee, f1, K[0], in[15], 8); @round(aaa, bbb, ccc, ddd, eee, f5, K[5], in[12], 6); + + @round(ee, aa, bb, cc, dd, f2, K[1], in[7], 7); @round(eee, aaa, bbb, ccc, ddd, f4, K[6], in[6], 9); + @round(dd, ee, aa, bb, cc, f2, K[1], in[4], 6); @round(ddd, eee, aaa, bbb, ccc, f4, K[6], in[11], 13); + @round(cc, dd, ee, aa, bb, f2, K[1], in[13], 8); @round(ccc, ddd, eee, aaa, bbb, f4, K[6], in[3], 15); + @round(bb, cc, dd, ee, aa, f2, K[1], in[1], 13); @round(bbb, ccc, ddd, eee, aaa, f4, K[6], in[7], 7); + @round(aa, bb, cc, dd, ee, f2, K[1], in[10], 11); @round(aaa, bbb, ccc, ddd, eee, f4, K[6], in[0], 12); + @round(ee, aa, bb, cc, dd, f2, K[1], in[6], 9); @round(eee, aaa, bbb, ccc, ddd, f4, K[6], in[13], 8); + @round(dd, ee, aa, bb, cc, f2, K[1], in[15], 7); @round(ddd, eee, aaa, bbb, ccc, f4, K[6], in[5], 9); + @round(cc, dd, ee, aa, bb, f2, K[1], in[3], 15); @round(ccc, ddd, eee, aaa, bbb, f4, K[6], in[10], 11); + @round(bb, cc, dd, ee, aa, f2, K[1], in[12], 7); @round(bbb, ccc, ddd, eee, aaa, f4, K[6], in[14], 7); + @round(aa, bb, cc, dd, ee, f2, K[1], in[0], 12); @round(aaa, bbb, ccc, ddd, eee, f4, K[6], in[15], 7); + @round(ee, aa, bb, cc, dd, f2, K[1], in[9], 15); @round(eee, aaa, bbb, ccc, ddd, f4, K[6], in[8], 12); + @round(dd, ee, aa, bb, cc, f2, K[1], in[5], 9); @round(ddd, eee, aaa, bbb, ccc, f4, K[6], in[12], 7); + @round(cc, dd, ee, aa, bb, f2, K[1], in[2], 11); @round(ccc, ddd, eee, aaa, bbb, f4, K[6], in[4], 6); + @round(bb, cc, dd, ee, aa, f2, K[1], in[14], 7); @round(bbb, ccc, ddd, eee, aaa, f4, K[6], in[9], 15); + @round(aa, bb, cc, dd, ee, f2, K[1], in[11], 13); @round(aaa, bbb, ccc, ddd, eee, f4, K[6], in[1], 13); + @round(ee, aa, bb, cc, dd, f2, K[1], in[8], 12); @round(eee, aaa, bbb, ccc, ddd, f4, K[6], in[2], 11); + + @round(dd, ee, aa, bb, cc, f3, K[2], in[3], 11); @round(ddd, eee, aaa, bbb, ccc, f3, K[7], in[15], 9); + @round(cc, dd, ee, aa, bb, f3, K[2], in[10], 13); @round(ccc, ddd, eee, aaa, bbb, f3, K[7], in[5], 7); + @round(bb, cc, dd, ee, aa, f3, K[2], in[14], 6); @round(bbb, ccc, ddd, eee, aaa, f3, K[7], in[1], 15); + @round(aa, bb, cc, dd, ee, f3, K[2], in[4], 7); @round(aaa, bbb, ccc, ddd, eee, f3, K[7], in[3], 11); + @round(ee, aa, bb, cc, dd, f3, K[2], in[9], 14); @round(eee, aaa, bbb, ccc, ddd, f3, K[7], in[7], 8); + @round(dd, ee, aa, bb, cc, f3, K[2], in[15], 9); @round(ddd, eee, aaa, bbb, ccc, f3, K[7], in[14], 6); + @round(cc, dd, ee, aa, bb, f3, K[2], in[8], 13); @round(ccc, ddd, eee, aaa, bbb, f3, K[7], in[6], 6); + @round(bb, cc, dd, ee, aa, f3, K[2], in[1], 15); @round(bbb, ccc, ddd, eee, aaa, f3, K[7], in[9], 14); + @round(aa, bb, cc, dd, ee, f3, K[2], in[2], 14); @round(aaa, bbb, ccc, ddd, eee, f3, K[7], in[11], 12); + @round(ee, aa, bb, cc, dd, f3, K[2], in[7], 8); @round(eee, aaa, bbb, ccc, ddd, f3, K[7], in[8], 13); + @round(dd, ee, aa, bb, cc, f3, K[2], in[0], 13); @round(ddd, eee, aaa, bbb, ccc, f3, K[7], in[12], 5); + @round(cc, dd, ee, aa, bb, f3, K[2], in[6], 6); @round(ccc, ddd, eee, aaa, bbb, f3, K[7], in[2], 14); + @round(bb, cc, dd, ee, aa, f3, K[2], in[13], 5); @round(bbb, ccc, ddd, eee, aaa, f3, K[7], in[10], 13); + @round(aa, bb, cc, dd, ee, f3, K[2], in[11], 12); @round(aaa, bbb, ccc, ddd, eee, f3, K[7], in[0], 13); + @round(ee, aa, bb, cc, dd, f3, K[2], in[5], 7); @round(eee, aaa, bbb, ccc, ddd, f3, K[7], in[4], 7); + @round(dd, ee, aa, bb, cc, f3, K[2], in[12], 5); @round(ddd, eee, aaa, bbb, ccc, f3, K[7], in[13], 5); + + @round(cc, dd, ee, aa, bb, f4, K[3], in[1], 11); @round(ccc, ddd, eee, aaa, bbb, f2, K[8], in[8], 15); + @round(bb, cc, dd, ee, aa, f4, K[3], in[9], 12); @round(bbb, ccc, ddd, eee, aaa, f2, K[8], in[6], 5); + @round(aa, bb, cc, dd, ee, f4, K[3], in[11], 14); @round(aaa, bbb, ccc, ddd, eee, f2, K[8], in[4], 8); + @round(ee, aa, bb, cc, dd, f4, K[3], in[10], 15); @round(eee, aaa, bbb, ccc, ddd, f2, K[8], in[1], 11); + @round(dd, ee, aa, bb, cc, f4, K[3], in[0], 14); @round(ddd, eee, aaa, bbb, ccc, f2, K[8], in[3], 14); + @round(cc, dd, ee, aa, bb, f4, K[3], in[8], 15); @round(ccc, ddd, eee, aaa, bbb, f2, K[8], in[11], 14); + @round(bb, cc, dd, ee, aa, f4, K[3], in[12], 9); @round(bbb, ccc, ddd, eee, aaa, f2, K[8], in[15], 6); + @round(aa, bb, cc, dd, ee, f4, K[3], in[4], 8); @round(aaa, bbb, ccc, ddd, eee, f2, K[8], in[0], 14); + @round(ee, aa, bb, cc, dd, f4, K[3], in[13], 9); @round(eee, aaa, bbb, ccc, ddd, f2, K[8], in[5], 6); + @round(dd, ee, aa, bb, cc, f4, K[3], in[3], 14); @round(ddd, eee, aaa, bbb, ccc, f2, K[8], in[12], 9); + @round(cc, dd, ee, aa, bb, f4, K[3], in[7], 5); @round(ccc, ddd, eee, aaa, bbb, f2, K[8], in[2], 12); + @round(bb, cc, dd, ee, aa, f4, K[3], in[15], 6); @round(bbb, ccc, ddd, eee, aaa, f2, K[8], in[13], 9); + @round(aa, bb, cc, dd, ee, f4, K[3], in[14], 8); @round(aaa, bbb, ccc, ddd, eee, f2, K[8], in[9], 12); + @round(ee, aa, bb, cc, dd, f4, K[3], in[5], 6); @round(eee, aaa, bbb, ccc, ddd, f2, K[8], in[7], 5); + @round(dd, ee, aa, bb, cc, f4, K[3], in[6], 5); @round(ddd, eee, aaa, bbb, ccc, f2, K[8], in[10], 15); + @round(cc, dd, ee, aa, bb, f4, K[3], in[2], 12); @round(ccc, ddd, eee, aaa, bbb, f2, K[8], in[14], 8); + + @round(bb, cc, dd, ee, aa, f5, K[4], in[4], 9); @round(bbb, ccc, ddd, eee, aaa, f1, 0, in[12], 8); + @round(aa, bb, cc, dd, ee, f5, K[4], in[0], 15); @round(aaa, bbb, ccc, ddd, eee, f1, 0, in[15], 5); + @round(ee, aa, bb, cc, dd, f5, K[4], in[5], 5); @round(eee, aaa, bbb, ccc, ddd, f1, 0, in[10], 12); + @round(dd, ee, aa, bb, cc, f5, K[4], in[9], 11); @round(ddd, eee, aaa, bbb, ccc, f1, 0, in[4], 9); + @round(cc, dd, ee, aa, bb, f5, K[4], in[7], 6); @round(ccc, ddd, eee, aaa, bbb, f1, 0, in[1], 12); + @round(bb, cc, dd, ee, aa, f5, K[4], in[12], 8); @round(bbb, ccc, ddd, eee, aaa, f1, 0, in[5], 5); + @round(aa, bb, cc, dd, ee, f5, K[4], in[2], 13); @round(aaa, bbb, ccc, ddd, eee, f1, 0, in[8], 14); + @round(ee, aa, bb, cc, dd, f5, K[4], in[10], 12); @round(eee, aaa, bbb, ccc, ddd, f1, 0, in[7], 6); + @round(dd, ee, aa, bb, cc, f5, K[4], in[14], 5); @round(ddd, eee, aaa, bbb, ccc, f1, 0, in[6], 8); + @round(cc, dd, ee, aa, bb, f5, K[4], in[1], 12); @round(ccc, ddd, eee, aaa, bbb, f1, 0, in[2], 13); + @round(bb, cc, dd, ee, aa, f5, K[4], in[3], 13); @round(bbb, ccc, ddd, eee, aaa, f1, 0, in[13], 6); + @round(aa, bb, cc, dd, ee, f5, K[4], in[8], 14); @round(aaa, bbb, ccc, ddd, eee, f1, 0, in[14], 5); + @round(ee, aa, bb, cc, dd, f5, K[4], in[11], 11); @round(eee, aaa, bbb, ccc, ddd, f1, 0, in[0], 15); + @round(dd, ee, aa, bb, cc, f5, K[4], in[6], 8); @round(ddd, eee, aaa, bbb, ccc, f1, 0, in[3], 13); + @round(cc, dd, ee, aa, bb, f5, K[4], in[15], 5); @round(ccc, ddd, eee, aaa, bbb, f1, 0, in[9], 11); + @round(bb, cc, dd, ee, aa, f5, K[4], in[13], 6); @round(bbb, ccc, ddd, eee, aaa, f1, 0, in[11], 11); + + ddd += cc + state[1]; + state[1] = state[2] + dd + eee; + state[2] = state[3] + ee + aaa; + state[3] = state[4] + aa + bbb; + state[4] = state[0] + bb + ccc; + state[0] = ddd; + + $case 256: + aa = state[0]; + bb = state[1]; + cc = state[2]; + dd = state[3]; + aaa = state[4]; + bbb = state[5]; + ccc = state[6]; + ddd = state[7]; + + @round(aa, bb, cc, dd, 0, f1, K[0], in[0], 11); @round(aaa, bbb, ccc, ddd, 0, f4, K[5], in[5], 8); + @round(dd, aa, bb, cc, 0, f1, K[0], in[1], 14); @round(ddd, aaa, bbb, ccc, 0, f4, K[5], in[14], 9); + @round(cc, dd, aa, bb, 0, f1, K[0], in[2], 15); @round(ccc, ddd, aaa, bbb, 0, f4, K[5], in[7], 9); + @round(bb, cc, dd, aa, 0, f1, K[0], in[3], 12); @round(bbb, ccc, ddd, aaa, 0, f4, K[5], in[0], 11); + @round(aa, bb, cc, dd, 0, f1, K[0], in[4], 5); @round(aaa, bbb, ccc, ddd, 0, f4, K[5], in[9], 13); + @round(dd, aa, bb, cc, 0, f1, K[0], in[5], 8); @round(ddd, aaa, bbb, ccc, 0, f4, K[5], in[2], 15); + @round(cc, dd, aa, bb, 0, f1, K[0], in[6], 7); @round(ccc, ddd, aaa, bbb, 0, f4, K[5], in[11], 15); + @round(bb, cc, dd, aa, 0, f1, K[0], in[7], 9); @round(bbb, ccc, ddd, aaa, 0, f4, K[5], in[4], 5); + @round(aa, bb, cc, dd, 0, f1, K[0], in[8], 11); @round(aaa, bbb, ccc, ddd, 0, f4, K[5], in[13], 7); + @round(dd, aa, bb, cc, 0, f1, K[0], in[9], 13); @round(ddd, aaa, bbb, ccc, 0, f4, K[5], in[6], 7); + @round(cc, dd, aa, bb, 0, f1, K[0], in[10], 14); @round(ccc, ddd, aaa, bbb, 0, f4, K[5], in[15], 8); + @round(bb, cc, dd, aa, 0, f1, K[0], in[11], 15); @round(bbb, ccc, ddd, aaa, 0, f4, K[5], in[8], 11); + @round(aa, bb, cc, dd, 0, f1, K[0], in[12], 6); @round(aaa, bbb, ccc, ddd, 0, f4, K[5], in[1], 14); + @round(dd, aa, bb, cc, 0, f1, K[0], in[13], 7); @round(ddd, aaa, bbb, ccc, 0, f4, K[5], in[10], 14); + @round(cc, dd, aa, bb, 0, f1, K[0], in[14], 9); @round(ccc, ddd, aaa, bbb, 0, f4, K[5], in[3], 12); + @round(bb, cc, dd, aa, 0, f1, K[0], in[15], 8); @round(bbb, ccc, ddd, aaa, 0, f4, K[5], in[12], 6); + + @swap(aa, aaa); + + @round(aa, bb, cc, dd, 0, f2, K[1], in[7], 7); @round(aaa, bbb, ccc, ddd, 0, f3, K[6], in[6], 9); + @round(dd, aa, bb, cc, 0, f2, K[1], in[4], 6); @round(ddd, aaa, bbb, ccc, 0, f3, K[6], in[11], 13); + @round(cc, dd, aa, bb, 0, f2, K[1], in[13], 8); @round(ccc, ddd, aaa, bbb, 0, f3, K[6], in[3], 15); + @round(bb, cc, dd, aa, 0, f2, K[1], in[1], 13); @round(bbb, ccc, ddd, aaa, 0, f3, K[6], in[7], 7); + @round(aa, bb, cc, dd, 0, f2, K[1], in[10], 11); @round(aaa, bbb, ccc, ddd, 0, f3, K[6], in[0], 12); + @round(dd, aa, bb, cc, 0, f2, K[1], in[6], 9); @round(ddd, aaa, bbb, ccc, 0, f3, K[6], in[13], 8); + @round(cc, dd, aa, bb, 0, f2, K[1], in[15], 7); @round(ccc, ddd, aaa, bbb, 0, f3, K[6], in[5], 9); + @round(bb, cc, dd, aa, 0, f2, K[1], in[3], 15); @round(bbb, ccc, ddd, aaa, 0, f3, K[6], in[10], 11); + @round(aa, bb, cc, dd, 0, f2, K[1], in[12], 7); @round(aaa, bbb, ccc, ddd, 0, f3, K[6], in[14], 7); + @round(dd, aa, bb, cc, 0, f2, K[1], in[0], 12); @round(ddd, aaa, bbb, ccc, 0, f3, K[6], in[15], 7); + @round(cc, dd, aa, bb, 0, f2, K[1], in[9], 15); @round(ccc, ddd, aaa, bbb, 0, f3, K[6], in[8], 12); + @round(bb, cc, dd, aa, 0, f2, K[1], in[5], 9); @round(bbb, ccc, ddd, aaa, 0, f3, K[6], in[12], 7); + @round(aa, bb, cc, dd, 0, f2, K[1], in[2], 11); @round(aaa, bbb, ccc, ddd, 0, f3, K[6], in[4], 6); + @round(dd, aa, bb, cc, 0, f2, K[1], in[14], 7); @round(ddd, aaa, bbb, ccc, 0, f3, K[6], in[9], 15); + @round(cc, dd, aa, bb, 0, f2, K[1], in[11], 13); @round(ccc, ddd, aaa, bbb, 0, f3, K[6], in[1], 13); + @round(bb, cc, dd, aa, 0, f2, K[1], in[8], 12); @round(bbb, ccc, ddd, aaa, 0, f3, K[6], in[2], 11); + + @swap(bb, bbb); + + @round(aa, bb, cc, dd, 0, f3, K[2], in[3], 11); @round(aaa, bbb, ccc, ddd, 0, f2, K[7], in[15], 9); + @round(dd, aa, bb, cc, 0, f3, K[2], in[10], 13); @round(ddd, aaa, bbb, ccc, 0, f2, K[7], in[5], 7); + @round(cc, dd, aa, bb, 0, f3, K[2], in[14], 6); @round(ccc, ddd, aaa, bbb, 0, f2, K[7], in[1], 15); + @round(bb, cc, dd, aa, 0, f3, K[2], in[4], 7); @round(bbb, ccc, ddd, aaa, 0, f2, K[7], in[3], 11); + @round(aa, bb, cc, dd, 0, f3, K[2], in[9], 14); @round(aaa, bbb, ccc, ddd, 0, f2, K[7], in[7], 8); + @round(dd, aa, bb, cc, 0, f3, K[2], in[15], 9); @round(ddd, aaa, bbb, ccc, 0, f2, K[7], in[14], 6); + @round(cc, dd, aa, bb, 0, f3, K[2], in[8], 13); @round(ccc, ddd, aaa, bbb, 0, f2, K[7], in[6], 6); + @round(bb, cc, dd, aa, 0, f3, K[2], in[1], 15); @round(bbb, ccc, ddd, aaa, 0, f2, K[7], in[9], 14); + @round(aa, bb, cc, dd, 0, f3, K[2], in[2], 14); @round(aaa, bbb, ccc, ddd, 0, f2, K[7], in[11], 12); + @round(dd, aa, bb, cc, 0, f3, K[2], in[7], 8); @round(ddd, aaa, bbb, ccc, 0, f2, K[7], in[8], 13); + @round(cc, dd, aa, bb, 0, f3, K[2], in[0], 13); @round(ccc, ddd, aaa, bbb, 0, f2, K[7], in[12], 5); + @round(bb, cc, dd, aa, 0, f3, K[2], in[6], 6); @round(bbb, ccc, ddd, aaa, 0, f2, K[7], in[2], 14); + @round(aa, bb, cc, dd, 0, f3, K[2], in[13], 5); @round(aaa, bbb, ccc, ddd, 0, f2, K[7], in[10], 13); + @round(dd, aa, bb, cc, 0, f3, K[2], in[11], 12); @round(ddd, aaa, bbb, ccc, 0, f2, K[7], in[0], 13); + @round(cc, dd, aa, bb, 0, f3, K[2], in[5], 7); @round(ccc, ddd, aaa, bbb, 0, f2, K[7], in[4], 7); + @round(bb, cc, dd, aa, 0, f3, K[2], in[12], 5); @round(bbb, ccc, ddd, aaa, 0, f2, K[7], in[13], 5); + + @swap(cc, ccc); + + @round(aa, bb, cc, dd, 0, f4, K[3], in[1], 11); @round(aaa, bbb, ccc, ddd, 0, f1, 0, in[8], 15); + @round(dd, aa, bb, cc, 0, f4, K[3], in[9], 12); @round(ddd, aaa, bbb, ccc, 0, f1, 0, in[6], 5); + @round(cc, dd, aa, bb, 0, f4, K[3], in[11], 14); @round(ccc, ddd, aaa, bbb, 0, f1, 0, in[4], 8); + @round(bb, cc, dd, aa, 0, f4, K[3], in[10], 15); @round(bbb, ccc, ddd, aaa, 0, f1, 0, in[1], 11); + @round(aa, bb, cc, dd, 0, f4, K[3], in[0], 14); @round(aaa, bbb, ccc, ddd, 0, f1, 0, in[3], 14); + @round(dd, aa, bb, cc, 0, f4, K[3], in[8], 15); @round(ddd, aaa, bbb, ccc, 0, f1, 0, in[11], 14); + @round(cc, dd, aa, bb, 0, f4, K[3], in[12], 9); @round(ccc, ddd, aaa, bbb, 0, f1, 0, in[15], 6); + @round(bb, cc, dd, aa, 0, f4, K[3], in[4], 8); @round(bbb, ccc, ddd, aaa, 0, f1, 0, in[0], 14); + @round(aa, bb, cc, dd, 0, f4, K[3], in[13], 9); @round(aaa, bbb, ccc, ddd, 0, f1, 0, in[5], 6); + @round(dd, aa, bb, cc, 0, f4, K[3], in[3], 14); @round(ddd, aaa, bbb, ccc, 0, f1, 0, in[12], 9); + @round(cc, dd, aa, bb, 0, f4, K[3], in[7], 5); @round(ccc, ddd, aaa, bbb, 0, f1, 0, in[2], 12); + @round(bb, cc, dd, aa, 0, f4, K[3], in[15], 6); @round(bbb, ccc, ddd, aaa, 0, f1, 0, in[13], 9); + @round(aa, bb, cc, dd, 0, f4, K[3], in[14], 8); @round(aaa, bbb, ccc, ddd, 0, f1, 0, in[9], 12); + @round(dd, aa, bb, cc, 0, f4, K[3], in[5], 6); @round(ddd, aaa, bbb, ccc, 0, f1, 0, in[7], 5); + @round(cc, dd, aa, bb, 0, f4, K[3], in[6], 5); @round(ccc, ddd, aaa, bbb, 0, f1, 0, in[10], 15); + @round(bb, cc, dd, aa, 0, f4, K[3], in[2], 12); @round(bbb, ccc, ddd, aaa, 0, f1, 0, in[14], 8); + + @swap(dd, ddd); + + state[0] += aa; + state[1] += bb; + state[2] += cc; + state[3] += dd; + state[4] += aaa; + state[5] += bbb; + state[6] += ccc; + state[7] += ddd; + + $case 320: + aa = state[0]; + bb = state[1]; + cc = state[2]; + dd = state[3]; + ee = state[4]; + aaa = state[5]; + bbb = state[6]; + ccc = state[7]; + ddd = state[8]; + eee = state[9]; + + @round(aa, bb, cc, dd, ee, f1, K[0], in[0], 11); @round(aaa, bbb, ccc, ddd, eee, f5, K[5], in[5], 8); + @round(ee, aa, bb, cc, dd, f1, K[0], in[1], 14); @round(eee, aaa, bbb, ccc, ddd, f5, K[5], in[14], 9); + @round(dd, ee, aa, bb, cc, f1, K[0], in[2], 15); @round(ddd, eee, aaa, bbb, ccc, f5, K[5], in[7], 9); + @round(cc, dd, ee, aa, bb, f1, K[0], in[3], 12); @round(ccc, ddd, eee, aaa, bbb, f5, K[5], in[0], 11); + @round(bb, cc, dd, ee, aa, f1, K[0], in[4], 5); @round(bbb, ccc, ddd, eee, aaa, f5, K[5], in[9], 13); + @round(aa, bb, cc, dd, ee, f1, K[0], in[5], 8); @round(aaa, bbb, ccc, ddd, eee, f5, K[5], in[2], 15); + @round(ee, aa, bb, cc, dd, f1, K[0], in[6], 7); @round(eee, aaa, bbb, ccc, ddd, f5, K[5], in[11], 15); + @round(dd, ee, aa, bb, cc, f1, K[0], in[7], 9); @round(ddd, eee, aaa, bbb, ccc, f5, K[5], in[4], 5); + @round(cc, dd, ee, aa, bb, f1, K[0], in[8], 11); @round(ccc, ddd, eee, aaa, bbb, f5, K[5], in[13], 7); + @round(bb, cc, dd, ee, aa, f1, K[0], in[9], 13); @round(bbb, ccc, ddd, eee, aaa, f5, K[5], in[6], 7); + @round(aa, bb, cc, dd, ee, f1, K[0], in[10], 14); @round(aaa, bbb, ccc, ddd, eee, f5, K[5], in[15], 8); + @round(ee, aa, bb, cc, dd, f1, K[0], in[11], 15); @round(eee, aaa, bbb, ccc, ddd, f5, K[5], in[8], 11); + @round(dd, ee, aa, bb, cc, f1, K[0], in[12], 6); @round(ddd, eee, aaa, bbb, ccc, f5, K[5], in[1], 14); + @round(cc, dd, ee, aa, bb, f1, K[0], in[13], 7); @round(ccc, ddd, eee, aaa, bbb, f5, K[5], in[10], 14); + @round(bb, cc, dd, ee, aa, f1, K[0], in[14], 9); @round(bbb, ccc, ddd, eee, aaa, f5, K[5], in[3], 12); + @round(aa, bb, cc, dd, ee, f1, K[0], in[15], 8); @round(aaa, bbb, ccc, ddd, eee, f5, K[5], in[12], 6); + + @swap(aa, aaa); + + @round(ee, aa, bb, cc, dd, f2, K[1], in[7], 7); @round(eee, aaa, bbb, ccc, ddd, f4, K[6], in[6], 9); + @round(dd, ee, aa, bb, cc, f2, K[1], in[4], 6); @round(ddd, eee, aaa, bbb, ccc, f4, K[6], in[11], 13); + @round(cc, dd, ee, aa, bb, f2, K[1], in[13], 8); @round(ccc, ddd, eee, aaa, bbb, f4, K[6], in[3], 15); + @round(bb, cc, dd, ee, aa, f2, K[1], in[1], 13); @round(bbb, ccc, ddd, eee, aaa, f4, K[6], in[7], 7); + @round(aa, bb, cc, dd, ee, f2, K[1], in[10], 11); @round(aaa, bbb, ccc, ddd, eee, f4, K[6], in[0], 12); + @round(ee, aa, bb, cc, dd, f2, K[1], in[6], 9); @round(eee, aaa, bbb, ccc, ddd, f4, K[6], in[13], 8); + @round(dd, ee, aa, bb, cc, f2, K[1], in[15], 7); @round(ddd, eee, aaa, bbb, ccc, f4, K[6], in[5], 9); + @round(cc, dd, ee, aa, bb, f2, K[1], in[3], 15); @round(ccc, ddd, eee, aaa, bbb, f4, K[6], in[10], 11); + @round(bb, cc, dd, ee, aa, f2, K[1], in[12], 7); @round(bbb, ccc, ddd, eee, aaa, f4, K[6], in[14], 7); + @round(aa, bb, cc, dd, ee, f2, K[1], in[0], 12); @round(aaa, bbb, ccc, ddd, eee, f4, K[6], in[15], 7); + @round(ee, aa, bb, cc, dd, f2, K[1], in[9], 15); @round(eee, aaa, bbb, ccc, ddd, f4, K[6], in[8], 12); + @round(dd, ee, aa, bb, cc, f2, K[1], in[5], 9); @round(ddd, eee, aaa, bbb, ccc, f4, K[6], in[12], 7); + @round(cc, dd, ee, aa, bb, f2, K[1], in[2], 11); @round(ccc, ddd, eee, aaa, bbb, f4, K[6], in[4], 6); + @round(bb, cc, dd, ee, aa, f2, K[1], in[14], 7); @round(bbb, ccc, ddd, eee, aaa, f4, K[6], in[9], 15); + @round(aa, bb, cc, dd, ee, f2, K[1], in[11], 13); @round(aaa, bbb, ccc, ddd, eee, f4, K[6], in[1], 13); + @round(ee, aa, bb, cc, dd, f2, K[1], in[8], 12); @round(eee, aaa, bbb, ccc, ddd, f4, K[6], in[2], 11); + + @swap(bb, bbb); + + @round(dd, ee, aa, bb, cc, f3, K[2], in[3], 11); @round(ddd, eee, aaa, bbb, ccc, f3, K[7], in[15], 9); + @round(cc, dd, ee, aa, bb, f3, K[2], in[10], 13); @round(ccc, ddd, eee, aaa, bbb, f3, K[7], in[5], 7); + @round(bb, cc, dd, ee, aa, f3, K[2], in[14], 6); @round(bbb, ccc, ddd, eee, aaa, f3, K[7], in[1], 15); + @round(aa, bb, cc, dd, ee, f3, K[2], in[4], 7); @round(aaa, bbb, ccc, ddd, eee, f3, K[7], in[3], 11); + @round(ee, aa, bb, cc, dd, f3, K[2], in[9], 14); @round(eee, aaa, bbb, ccc, ddd, f3, K[7], in[7], 8); + @round(dd, ee, aa, bb, cc, f3, K[2], in[15], 9); @round(ddd, eee, aaa, bbb, ccc, f3, K[7], in[14], 6); + @round(cc, dd, ee, aa, bb, f3, K[2], in[8], 13); @round(ccc, ddd, eee, aaa, bbb, f3, K[7], in[6], 6); + @round(bb, cc, dd, ee, aa, f3, K[2], in[1], 15); @round(bbb, ccc, ddd, eee, aaa, f3, K[7], in[9], 14); + @round(aa, bb, cc, dd, ee, f3, K[2], in[2], 14); @round(aaa, bbb, ccc, ddd, eee, f3, K[7], in[11], 12); + @round(ee, aa, bb, cc, dd, f3, K[2], in[7], 8); @round(eee, aaa, bbb, ccc, ddd, f3, K[7], in[8], 13); + @round(dd, ee, aa, bb, cc, f3, K[2], in[0], 13); @round(ddd, eee, aaa, bbb, ccc, f3, K[7], in[12], 5); + @round(cc, dd, ee, aa, bb, f3, K[2], in[6], 6); @round(ccc, ddd, eee, aaa, bbb, f3, K[7], in[2], 14); + @round(bb, cc, dd, ee, aa, f3, K[2], in[13], 5); @round(bbb, ccc, ddd, eee, aaa, f3, K[7], in[10], 13); + @round(aa, bb, cc, dd, ee, f3, K[2], in[11], 12); @round(aaa, bbb, ccc, ddd, eee, f3, K[7], in[0], 13); + @round(ee, aa, bb, cc, dd, f3, K[2], in[5], 7); @round(eee, aaa, bbb, ccc, ddd, f3, K[7], in[4], 7); + @round(dd, ee, aa, bb, cc, f3, K[2], in[12], 5); @round(ddd, eee, aaa, bbb, ccc, f3, K[7], in[13], 5); + + @swap(cc, ccc); + + @round(cc, dd, ee, aa, bb, f4, K[3], in[1], 11); @round(ccc, ddd, eee, aaa, bbb, f2, K[8], in[8], 15); + @round(bb, cc, dd, ee, aa, f4, K[3], in[9], 12); @round(bbb, ccc, ddd, eee, aaa, f2, K[8], in[6], 5); + @round(aa, bb, cc, dd, ee, f4, K[3], in[11], 14); @round(aaa, bbb, ccc, ddd, eee, f2, K[8], in[4], 8); + @round(ee, aa, bb, cc, dd, f4, K[3], in[10], 15); @round(eee, aaa, bbb, ccc, ddd, f2, K[8], in[1], 11); + @round(dd, ee, aa, bb, cc, f4, K[3], in[0], 14); @round(ddd, eee, aaa, bbb, ccc, f2, K[8], in[3], 14); + @round(cc, dd, ee, aa, bb, f4, K[3], in[8], 15); @round(ccc, ddd, eee, aaa, bbb, f2, K[8], in[11], 14); + @round(bb, cc, dd, ee, aa, f4, K[3], in[12], 9); @round(bbb, ccc, ddd, eee, aaa, f2, K[8], in[15], 6); + @round(aa, bb, cc, dd, ee, f4, K[3], in[4], 8); @round(aaa, bbb, ccc, ddd, eee, f2, K[8], in[0], 14); + @round(ee, aa, bb, cc, dd, f4, K[3], in[13], 9); @round(eee, aaa, bbb, ccc, ddd, f2, K[8], in[5], 6); + @round(dd, ee, aa, bb, cc, f4, K[3], in[3], 14); @round(ddd, eee, aaa, bbb, ccc, f2, K[8], in[12], 9); + @round(cc, dd, ee, aa, bb, f4, K[3], in[7], 5); @round(ccc, ddd, eee, aaa, bbb, f2, K[8], in[2], 12); + @round(bb, cc, dd, ee, aa, f4, K[3], in[15], 6); @round(bbb, ccc, ddd, eee, aaa, f2, K[8], in[13], 9); + @round(aa, bb, cc, dd, ee, f4, K[3], in[14], 8); @round(aaa, bbb, ccc, ddd, eee, f2, K[8], in[9], 12); + @round(ee, aa, bb, cc, dd, f4, K[3], in[5], 6); @round(eee, aaa, bbb, ccc, ddd, f2, K[8], in[7], 5); + @round(dd, ee, aa, bb, cc, f4, K[3], in[6], 5); @round(ddd, eee, aaa, bbb, ccc, f2, K[8], in[10], 15); + @round(cc, dd, ee, aa, bb, f4, K[3], in[2], 12); @round(ccc, ddd, eee, aaa, bbb, f2, K[8], in[14], 8); + + @swap(dd, ddd); + + @round(bb, cc, dd, ee, aa, f5, K[4], in[4], 9); @round(bbb, ccc, ddd, eee, aaa, f1, 0, in[12], 8); + @round(aa, bb, cc, dd, ee, f5, K[4], in[0], 15); @round(aaa, bbb, ccc, ddd, eee, f1, 0, in[15], 5); + @round(ee, aa, bb, cc, dd, f5, K[4], in[5], 5); @round(eee, aaa, bbb, ccc, ddd, f1, 0, in[10], 12); + @round(dd, ee, aa, bb, cc, f5, K[4], in[9], 11); @round(ddd, eee, aaa, bbb, ccc, f1, 0, in[4], 9); + @round(cc, dd, ee, aa, bb, f5, K[4], in[7], 6); @round(ccc, ddd, eee, aaa, bbb, f1, 0, in[1], 12); + @round(bb, cc, dd, ee, aa, f5, K[4], in[12], 8); @round(bbb, ccc, ddd, eee, aaa, f1, 0, in[5], 5); + @round(aa, bb, cc, dd, ee, f5, K[4], in[2], 13); @round(aaa, bbb, ccc, ddd, eee, f1, 0, in[8], 14); + @round(ee, aa, bb, cc, dd, f5, K[4], in[10], 12); @round(eee, aaa, bbb, ccc, ddd, f1, 0, in[7], 6); + @round(dd, ee, aa, bb, cc, f5, K[4], in[14], 5); @round(ddd, eee, aaa, bbb, ccc, f1, 0, in[6], 8); + @round(cc, dd, ee, aa, bb, f5, K[4], in[1], 12); @round(ccc, ddd, eee, aaa, bbb, f1, 0, in[2], 13); + @round(bb, cc, dd, ee, aa, f5, K[4], in[3], 13); @round(bbb, ccc, ddd, eee, aaa, f1, 0, in[13], 6); + @round(aa, bb, cc, dd, ee, f5, K[4], in[8], 14); @round(aaa, bbb, ccc, ddd, eee, f1, 0, in[14], 5); + @round(ee, aa, bb, cc, dd, f5, K[4], in[11], 11); @round(eee, aaa, bbb, ccc, ddd, f1, 0, in[0], 15); + @round(dd, ee, aa, bb, cc, f5, K[4], in[6], 8); @round(ddd, eee, aaa, bbb, ccc, f1, 0, in[3], 13); + @round(cc, dd, ee, aa, bb, f5, K[4], in[15], 5); @round(ccc, ddd, eee, aaa, bbb, f1, 0, in[9], 11); + @round(bb, cc, dd, ee, aa, f5, K[4], in[13], 6); @round(bbb, ccc, ddd, eee, aaa, f1, 0, in[11], 11); + + @swap(ee, eee); + + state[0] += aa; + state[1] += bb; + state[2] += cc; + state[3] += dd; + state[4] += ee; + state[5] += aaa; + state[6] += bbb; + state[7] += ccc; + state[8] += ddd; + state[9] += eee; + + $default: + $error "Invalid digest size"; + $endswitch +} diff --git a/releasenotes.md b/releasenotes.md index 7fc8a399a..9151f9dd4 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -39,6 +39,7 @@ - Pthread bindings correctly return Errno instead of CInt. - Return of Thread `join()` is now "@maydiscard". - Add `poly1305` one-time Message Authentication Code and associated tests. #2639 +- Add `ripemd` hashing and associated tests. #2663 - Add `chacha20` stream cipher and associated tests. #2643 - Add `BLAKE2` (optionally keyed) cryptographic hashing with associated tests. #2648 - Add `Elf32_Shdr` and `Elf64_Shdr` to `std::os::linux`. diff --git a/test/unit/stdlib/hash/ripemd.c3 b/test/unit/stdlib/hash/ripemd.c3 new file mode 100644 index 000000000..6ea894e84 --- /dev/null +++ b/test/unit/stdlib/hash/ripemd.c3 @@ -0,0 +1,174 @@ +// Copyright (c) 2025 Zack Puhl . All rights reserved. +// Use of this source code is governed by the MIT license +// a copy of which can be found in the LICENSE_STDLIB file. +module ripemd_tests @test; + +import std::hash::ripemd; +import std::collections; + + +fn void assert_finalization() +{ + static char[RipeMd{160}.sizeof] empty = {}; + RipeMd{160} ctx @noinit; + + ctx.init(); + test::@check(@as_char_view(ctx) != empty[..], "RIPE-MD cryptographic context is not initialized."); + + ctx.update("beep"); + (void)ctx.final(); + test::@check(@as_char_view(ctx) == empty[..], "RIPE-MD cryptographic context was not implicitly wiped upon finalization:\n\t%s.", @as_char_view(ctx)); +} + + +fn void empties() +{ + test::@check(ripemd::hash{128}("") == x'cdf26213a150dc3ecb610f18f6b38b46'); + test::@check(ripemd::hash{160}("") == x'9c1185a5c5e9fc54612808977ee8f548b2258d31'); + test::@check(ripemd::hash{256}("") == x'02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d'); + test::@check(ripemd::hash{320}("") == x'22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8'); +} + + +fn void basic() +{ + char[] phrase = "The quick brown fox jumps over the lazy dog"; + test::@check(ripemd::hash{128}(phrase) == x'3fa9b57f053c053fbe2735b2380db596'); + test::@check(ripemd::hash{160}(phrase) == x'37f332f68db77bd9d7edd4969571ad671cf9dd3b'); + test::@check(ripemd::hash{256}(phrase) == x'c3b0c2f764ac6d576a6c430fb61a6f2255b4fa833e094b1ba8c1e29b6353036f'); + test::@check(ripemd::hash{320}(phrase) == x'e7660e67549435c62141e51c9ab1dcc3b1ee9f65c0b3e561ae8f58c5dba3d21997781cd1cc6fbc34'); +} + +fn void basic_streamed() +{ + static char[][] expected = { + x'3fa9b57f053c053fbe2735b2380db596', + x'37f332f68db77bd9d7edd4969571ad671cf9dd3b', + x'c3b0c2f764ac6d576a6c430fb61a6f2255b4fa833e094b1ba8c1e29b6353036f', + x'e7660e67549435c62141e51c9ab1dcc3b1ee9f65c0b3e561ae8f58c5dba3d21997781cd1cc6fbc34' + }; + char[] phrase = "The quick brown fox jumps over the lazy dog"; + $foreach $i, $bits : ripemd::PERMISSIBLE_SIZES_BITS{128}: + { // le scope + RipeMd{$bits} r @noinit; + r.init(); + r.update(phrase[ : phrase.len/4 ]); + r.update(phrase[ 1*(phrase.len/4) : phrase.len/4 ]); + r.update(phrase[ 2*(phrase.len/4) : phrase.len/4 ]); + r.update(phrase[ 3*(phrase.len/4) .. ]); + test::@check(r.final()[..] == expected[$i]); + } + $endforeach +} + + +fn void large_input() +{ + char[] one_mb = mem::talloc_array(char, 1024*1024); + one_mb[..] = 0xA5; + + test::@check(ripemd::hash{128}(one_mb) == x'e8b57fa5f8415f7a17043b67509fc182'); + test::@check(ripemd::hash{160}(one_mb) == x'edac5dd2281c86b49b362269636ef1680283d291'); + test::@check(ripemd::hash{256}(one_mb) == x'c635c1763d2766e617f095fb3bb65ed3b533fb48a7ac127916a2f2ba1127d3cf'); + test::@check(ripemd::hash{320}(one_mb) == x'3173e524ea770b420c986974b486ea18d4558db55000e6db67784fe5fc091fe5fcc8bc80b7753c34'); +} + +fn void large_input_streamed() +{ + static char[][] expected = { + x'e8b57fa5f8415f7a17043b67509fc182', + x'edac5dd2281c86b49b362269636ef1680283d291', + x'c635c1763d2766e617f095fb3bb65ed3b533fb48a7ac127916a2f2ba1127d3cf', + x'3173e524ea770b420c986974b486ea18d4558db55000e6db67784fe5fc091fe5fcc8bc80b7753c34' + }; + char[] one_mb = mem::talloc_array(char, 1024*1024); + one_mb[..] = 0xA5; + $foreach $i, $bits : ripemd::PERMISSIBLE_SIZES_BITS{128}: + { + RipeMd{$bits} r @noinit; + r.init(); + r.update(one_mb[ : one_mb.len/4 ]); + r.update(one_mb[ 1*(one_mb.len/4) : one_mb.len/4 ]); + r.update(one_mb[ 2*(one_mb.len/4) : one_mb.len/4 ]); + r.update(one_mb[ 3*(one_mb.len/4) .. ]); + test::@check(r.final()[..] == expected[$i]); + } + $endforeach +} + +fn void large_input_streamed_per_byte() +{ + static char[][] expected = { + x'e8b57fa5f8415f7a17043b67509fc182', + x'edac5dd2281c86b49b362269636ef1680283d291', + x'c635c1763d2766e617f095fb3bb65ed3b533fb48a7ac127916a2f2ba1127d3cf', + x'3173e524ea770b420c986974b486ea18d4558db55000e6db67784fe5fc091fe5fcc8bc80b7753c34' + }; + char[] one_mb = mem::talloc_array(char, 1024*1024); + one_mb[..] = 0xA5; + $foreach $i, $bits : ripemd::PERMISSIBLE_SIZES_BITS{128}: + { + RipeMd{$bits} r @noinit; + r.init(); + foreach (&c : one_mb) r.update(c[:1]); + test::@check(r.final()[..] == expected[$i]); + } + $endforeach +} + + +fn void walk_lengths() +{ + foreach (arr : CALCULATED_HASHES) + { + test::@check(ripemd::hash{128}(arr[0])[..] == arr[1]); + test::@check(ripemd::hash{160}(arr[0])[..] == arr[2]); + test::@check(ripemd::hash{256}(arr[0])[..] == arr[3]); + test::@check(ripemd::hash{320}(arr[0])[..] == arr[4]); + } +} + +fn void walk_lengths_streamed() +{ + foreach (arr : CALCULATED_HASHES) + { + $foreach $i, $bits : ripemd::PERMISSIBLE_SIZES_BITS{128}: + { + RipeMd{$bits} r @noinit; + r.init(); + r.update(arr[0][ : arr[0].len/4 ]); + r.update(arr[0][ 1*(arr[0].len/4) : arr[0].len/4 ]); + r.update(arr[0][ 2*(arr[0].len/4) : arr[0].len/4 ]); + r.update(arr[0][ 3*(arr[0].len/4) .. ]); + test::@check(r.final()[..] == arr[$i + 1]); + } + $endforeach + } +} + +const char[][5][] CALCULATED_HASHES = { + // various <1 block + { "a", x'86be7afa339d0fc7cfc785e72f578d33', x'0bdc9d2d256b3ee9daae347be6f4dc835a467ffe', x'f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925', x'ce78850638f92658a5a585097579926dda667a5716562cfcf6fbe77f63542f99b04705d6970dff5d' }, + { "abcde", x'a0a954be2a779bfb2129b72110c5782d', x'973398b6e6c6cfa6b5e6a5173f195ce3274bf828', x'81d8b58a3110a9139b4ddeccb031409e8af023067cf4c6f0b701dab9ecc0eb4e', x'a94dc1bc825db64e97718305ce36bfef32cc5410a630999678bcd89cc38c424269012ec8c5a95830' }, + { "abcdeabcd", x'635cd0a53e0dd5165cac8ddbee7652cd', x'807e17a70c332849b16781f6ee7922f5e7db63f8', x'31b029446e713234e05d17b7b1007c97ed26b6c536b28c054db102e02f34b12b', x'46d38e1f11d62ca12e0597a975b072bf2e2c6f11bea0e4b304d4c2da54fb06b21282d7140f312089' }, + { "abcdeabcdabcdeab", x'23465727108702623665cf26343522b9', x'8547fee8ca4574daae85bdccb86ef55c5fe2846f', x'63f27e77a68dc95be6bad32d16b7760448571e5042dade5a1238db9fa693fea3', x'bfd1594d518db7a40a3dede4a45201db1051ce8a8d0261f83c1725ffe4baf0a8ace7f069a562d79f' }, + { "abcdeabcdabcdeabc", x'b4648632cbb6a15b81f512a33b723473', x'9b7c05456e9168db1d00bb51e16370a3593b9465', x'b6f9371183c1231fa28eb02b0b005848bf9490023811cdc6d724e7c2e722ce85', x'06dfd96b1550647833dbb2e29a5ae470e5125d88e4876b9bb5ba10302fbd4d85fbe789bf41ba569a' }, + { "abcdeabcdabcdeabcabcdeabcdabcdeabcdea", x'1e22bb88890fab194b3d6bd8b9def772', x'4ecc7066704497cf3dbb8dfcff22bcbc4892f642', x'2bacfe18130dec744e97499a49f02ba28e811c931db3f13f7b088d0af409a8fe', x'cdf8a2dda089fdeb5dcad3eb379470bbdbb4ad730195d791b36f0979d2c45190c64a79f097efe0bf' }, + { "abcdeabcdabcdeabcabcdeabcdabcdeabcdeab", x'db41ba3b4ff1d41055374c929a89e0e5', x'8e80b382727b7ea13ad7698fc07fa1c58e1ad451', x'779ccb4ea231bcbe0285f03202a332ac46e86e1434d0aa6e996e71c554902933', x'55aaccefb7e027aed5305a752576e7deb8afd3c6317d1a47fd9545b02c70405b12a4d69a14f881c0' }, + { "abcdeabcdabcdeabcabcdeabcdabcdeabcdeabcde", x'00a8da1bdcca00dc7538ac890266acb8', x'efce1e52dd937bcaf04aeea66db30d3a36af8d9d', x'5e2dd99cec7e02907910f14526e4aea39b5d1d9bc148ebbea685c26dfd965619', x'8c135e36adce8e3869cf1bfd671fa908585cfa415a345f10c1e188b9622d5400648a6fd6e7be9296' }, + { "abcdeabcdabcdeabcabcdeabcdabcdeabcdeabcdeabcd", x'c09e2bbaf5d230c58227c77a59e13c10', x'738c221b1c1a63f29fc1616389395825493f6053', x'ec17e9420c1268dc293591b3217b11d9bce2a57fcfcb9efac3e328079684e348', x'5ace0ffaa6b20e277794a0b38de747f6f6b69a1b44141a9dc835eeb0cd8802370cc3f1cd72638e1d' }, + { "abcdeabcdabcdeabcabcdeabcdabcdeabcdeabcdeabcdeabcde", x'14e8d04a7f0841155958c9c0322234ac', x'5c459f85203088a16df8eb0535b625c847a3a978', x'64b720261a622380a595707ebb14f612be3aff551454886736427639a71912e0', x'227d94ced760cfdcfc80554cbd32d77058cd84b2ba970a0c060a24725dc5c8de89eed859b0df1e4e' }, + // near one-block boundary + { "abcdeabcdabcdeabcabcdeabcdabcdeabcdeabcdeabcdeabcdeabcdeabcdea", x'f4509de22563bd3b33f3baf5a7a8ae1a', x'510cbbfc90525eb4215ea43d667ecced08121f46', x'681eca70274324398280d03750b78d90d1ca0d3242687d64afe6c12f87e59f2a', x'20e2e1b19b523cddd421fca650608b12bc0ba194b2279d1992622ee4e98a29e76db7acb9f8b8fb34' }, + { "abcdeabcdabcdeabcabcdeabcdabcdeabcdeabcdeabcdeabcdeabcdeabcdeab", x'ba653f72f0de768b94bdaa2d8b3a4780', x'e114478d20e436c0e09222750c1606235308e25a', x'176f0f5f132f0f5aee2be93658afb7b82ce8ed5918016cdf778acad368d45ade', x'f41eee99b9a7cdee313ba7852315a4ad49fde956e28a5858b4e0590ef437ec427c6b71c688e07b32' }, + { "abcdeabcdabcdeabcabcdeabcdabcdeabcdeabcdeabcdeabcdeabcdeabcdeabc", x'644008f8e0fcd0a97b7840b7c12691c8', x'fd47e805822cb81c0efb8da28c51420c0e33b5a9', x'25ca9b0b822a0e2ae24ff98b709d2c88966364c9c19975c3cddc155b94787606', x'2ba0071efd27440518674432ad6d14c0cf0b53631123eae655aa1c3d08b8fecb4693ce2f98494f3b' }, + { "abcdeabcdabcdeabcabcdeabcdabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcd", x'e7033b021f73230ebb634edc90fb59ae', x'59b27afdf089f7a20e09614468da32430358f5cd', x'515c7c8184253313cdb98a5341dbeeeeb889f153d867bfc8cffd667f3596aed8', x'ef03ee21dda0c64ea9a28ddc4bc935a486668b237bba83b89a512e4e7d2a08a00b5494c4ce74425b' }, + { "abcdeabcdabcdeabcabcdeabcdabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde", x'40b12f14498a838e671bf63070ea61e0', x'ea5d980bc60a4dbc5724773da49bb8d4a5e922e3', x'4fe1f00eba7869455852dbabcbd56566a8d24177fb66d67696d3c27aaaefe3a0', x'c60fe39e9ab75f960319cc2f4b7af805bb635e53082a77748234a1ef86323ea01891a13d70f28c01' }, + // near two-block boundary + { "abcdeabcdabcdeabcabcdeabcdabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdabcdeabcabcdeabcdabcdeabcdeabcdeabcdeabcdeabcdeabcde", + x'ae8cc9d8144b9e57de33b36c3ca6185f', x'2465de27e6e0255ffc1e28a6d4731ab59ce8e43b', x'a4a8d0f209f496a7f9008dec19b72c138887dac2a3b72f4bb25632b18ca0d73e', x'425ecf1a6e59b76078478ebc5a4ecf90a27742cfea19626f0f7785e2c62d8b5fddf03c5b213c6f36' }, + { "abcdeabcdabcdeabcabcdeabcdabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdabcdeabcabcdeabcdabcdeabcdeabcdeabcdeabcdeabcdeabcdea", + x'5cc7dbc0b33fcef3927d13584459e925', x'7ea3aabcbb9331b5b2374cb6cb663d10d377316d', x'11689e37b81c568a3be70678e4697a0f00c76a55642d57897d0d6e470a289352', x'820979996008b7bfec51e258a0152336c875917decf1ab5ab0ece063cf28cf4421977b70138ce92a' }, + { "abcdeabcdabcdeabcabcdeabcdabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdabcdeabcabcdeabcdabcdeabcdeabcdeabcdeabcdeabcdeabcdeab", + x'7184b353ae47499bdea3c71f6d4e9233', x'f1ab66b1cfb5a1ce6fedae1d6165e8e5629be43d', x'70edf63d3700f4b041c8b5737fb93ad329dab5711c8bd57beae7f696e1fdef45', x'10eeb15dd5397626ac7a2bd6dc07e19cdfb739acf4e134f928d6f087804cb767293a6f7ccb6705f2' }, +};