From 485cdbabe55f9650341a73c7d382238ced2c3826 Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Thu, 23 Apr 2026 11:45:05 +0200 Subject: [PATCH 01/17] Add benchmark for Ripemd160 --- bench/ripemd160.bench.mo | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 bench/ripemd160.bench.mo diff --git a/bench/ripemd160.bench.mo b/bench/ripemd160.bench.mo new file mode 100644 index 0000000..4667e65 --- /dev/null +++ b/bench/ripemd160.bench.mo @@ -0,0 +1,65 @@ +import Array "mo:core/Array"; +import Nat8 "mo:core/Nat8"; + +import Bench "mo:bench-helper"; + +import Ripemd160 "../src/Ripemd160"; + +module { + public func init() : Bench.V1 { + let schema : Bench.Schema = { + name = "RIPEMD-160"; + description = "RIPEMD-160 one-shot hash across message sizes, plus incremental digest"; + rows = ["hash (one-shot)", "Digest (incremental, 64-byte chunks)"]; + cols = ["len 0", "len 32", "len 64", "len 256", "len 1024"]; + }; + + let datas : [[Nat8]] = [ + [], + Array.tabulate(32, func i { Nat8.fromNat((i * 3 + 1) % 256) }), + Array.tabulate(64, func i { Nat8.fromNat((i * 7 + 5) % 256) }), + Array.tabulate(256, func i { Nat8.fromNat((i * 11 + 13) % 256) }), + Array.tabulate(1024, func i { Nat8.fromNat((i * 17 + 9) % 256) }), + ]; + + // Pre-split each input into 64-byte chunks for the incremental row. + let chunkedDatas : [[[Nat8]]] = Array.tabulate<[[Nat8]]>( + datas.size(), + func(ci) { + let data = datas[ci]; + let total = data.size(); + if (total == 0) { + []; + } else { + let nChunks = (total + 63) / 64; + Array.tabulate<[Nat8]>( + nChunks, + func(k) { + let start = k * 64; + let end = if (start + 64 < total) { start + 64 } else { total }; + Array.tabulate(end - start, func(j) { data[start + j] }); + }, + ); + }; + }, + ); + + func run(ri : Nat, ci : Nat) { + switch (ri) { + case (0) { + ignore Ripemd160.hash(datas[ci]); + }; + case (1) { + let d = Ripemd160.Digest(); + for (chunk in chunkedDatas[ci].values()) { + d.write(chunk); + }; + ignore d.sum(); + }; + case (_) {}; + }; + }; + + Bench.V1(schema, run); + }; +}; From 0b1f4eb464cfbbe66796d76ec60e4dc55309e5cb Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Thu, 23 Apr 2026 13:44:15 +0200 Subject: [PATCH 02/17] First step optimization by Opus 4.7 with input from Sha2 package About 50% reduction in instructions. --- src/Ripemd160.mo | 1035 +++++++++++++++------------------------------- 1 file changed, 323 insertions(+), 712 deletions(-) diff --git a/src/Ripemd160.mo b/src/Ripemd160.mo index ef14479..803d477 100644 --- a/src/Ripemd160.mo +++ b/src/Ripemd160.mo @@ -1,9 +1,9 @@ -import Nat "mo:core/Nat"; +import Nat8 "mo:core/Nat8"; +import Nat16 "mo:core/Nat16"; +import Nat32 "mo:core/Nat32"; import Nat64 "mo:core/Nat64"; import VarArray "mo:core/VarArray"; -import Common "Common"; - module { // Hash the given array and return finalized result. public func hash(array : [Nat8]) : [Nat8] { @@ -13,9 +13,23 @@ module { }; public class Digest() { + // Persistent chaining state: 5 Nat32 words (h0..h4). + // Stored inline in a [var Nat32] so per-block updates do not allocate. private let s : [var Nat32] = VarArray.repeat(0, 5); - private let buf : [var Nat8] = VarArray.repeat(0, 64); - private var bytes : Nat64 = 0; + + // Decoded message schedule for the block currently being assembled. + // Each slot holds one little-endian 32-bit word; bytes are folded in + // by writeByte and full 4-byte words are written wholesale by the + // fast path in write(). Stored inline in a [var Nat32] so updates + // inside the hot loop do not allocate. + private let msg : [var Nat32] = VarArray.repeat(0, 16); + + // Number of bytes accumulated into the current (partial) block, 0..63. + // Nat16 fits unboxed in mutable storage, avoiding heap traffic per byte. + private var i_msg : Nat16 = 0; + + // Number of complete 64-byte blocks already absorbed. + private var n_blocks : Nat64 = 0; private func initialize() { s[0] := 0x67452301; @@ -23,175 +37,42 @@ module { s[2] := 0x98BADCFE; s[3] := 0x10325476; s[4] := 0xC3D2E1F0; + i_msg := 0; + n_blocks := 0; + // msg slots are overwritten before being read, so no clear needed here. }; initialize(); public func reset() { - bytes := 0; initialize(); }; - private func f1(x : Nat32, y : Nat32, z : Nat32) : Nat32 { - x ^ y ^ z; - }; - - private func f2(x : Nat32, y : Nat32, z : Nat32) : Nat32 { - (x & y) | (^x & z); - }; - - private func f3(x : Nat32, y : Nat32, z : Nat32) : Nat32 { - (x | ^y) ^ z; - }; - - private func f4(x : Nat32, y : Nat32, z : Nat32) : Nat32 { - (x & z) | (y & ^z); - }; - - private func f5(x : Nat32, y : Nat32, z : Nat32) : Nat32 { - x ^ (y | ^z); - }; - - private func rol(x : Nat32, i : Nat32) : Nat32 { - (x << i) | (x >> (32 - i)); + private func rol(x : Nat32, r : Nat32) : Nat32 { + (x << r) | (x >> (32 - r)); }; - private func round( - a : Nat32, - _b : Nat32, - c : Nat32, - _d : Nat32, - e : Nat32, - f : Nat32, - x : Nat32, - k : Nat32, - r : Nat32, - ) : (Nat32, Nat32) { - (rol(a +% f +% x +% k, r) +% e, rol(c, 10)); - }; - - private func r11( - a : Nat32, - b : Nat32, - c : Nat32, - d : Nat32, - e : Nat32, - x : Nat32, - r : Nat32, - ) : (Nat32, Nat32) { - round(a, b, c, d, e, f1(b, c, d), x, 0, r); - }; - - private func r21( - a : Nat32, - b : Nat32, - c : Nat32, - d : Nat32, - e : Nat32, - x : Nat32, - r : Nat32, - ) : (Nat32, Nat32) { - round(a, b, c, d, e, f2(b, c, d), x, 0x5A827999, r); - }; - - private func r31( - a : Nat32, - b : Nat32, - c : Nat32, - d : Nat32, - e : Nat32, - x : Nat32, - r : Nat32, - ) : (Nat32, Nat32) { - round(a, b, c, d, e, f3(b, c, d), x, 0x6ED9EBA1, r); - }; - - private func r41( - a : Nat32, - b : Nat32, - c : Nat32, - d : Nat32, - e : Nat32, - x : Nat32, - r : Nat32, - ) : (Nat32, Nat32) { - round(a, b, c, d, e, f4(b, c, d), x, 0x8F1BBCDC, r); - }; - - private func r51( - a : Nat32, - b : Nat32, - c : Nat32, - d : Nat32, - e : Nat32, - x : Nat32, - r : Nat32, - ) : (Nat32, Nat32) { - round(a, b, c, d, e, f5(b, c, d), x, 0xA953FD4E, r); - }; - - private func r12( - a : Nat32, - b : Nat32, - c : Nat32, - d : Nat32, - e : Nat32, - x : Nat32, - r : Nat32, - ) : (Nat32, Nat32) { - round(a, b, c, d, e, f5(b, c, d), x, 0x50A28BE6, r); - }; + // Process the 16-word block currently held in msg, updating s. + // The round structure is the standard RIPEMD-160 two-line schedule + // with all 160 rounds inlined to avoid per-round tuple allocations. + private func transform() { + let w0 = msg[0]; + let w1 = msg[1]; + let w2 = msg[2]; + let w3 = msg[3]; + let w4 = msg[4]; + let w5 = msg[5]; + let w6 = msg[6]; + let w7 = msg[7]; + let w8 = msg[8]; + let w9 = msg[9]; + let w10 = msg[10]; + let w11 = msg[11]; + let w12 = msg[12]; + let w13 = msg[13]; + let w14 = msg[14]; + let w15 = msg[15]; - private func r22( - a : Nat32, - b : Nat32, - c : Nat32, - d : Nat32, - e : Nat32, - x : Nat32, - r : Nat32, - ) : (Nat32, Nat32) { - round(a, b, c, d, e, f4(b, c, d), x, 0x5C4DD124, r); - }; - - private func r32( - a : Nat32, - b : Nat32, - c : Nat32, - d : Nat32, - e : Nat32, - x : Nat32, - r : Nat32, - ) : (Nat32, Nat32) { - round(a, b, c, d, e, f3(b, c, d), x, 0x6D703EF3, r); - }; - - private func r42( - a : Nat32, - b : Nat32, - c : Nat32, - d : Nat32, - e : Nat32, - x : Nat32, - r : Nat32, - ) : (Nat32, Nat32) { - round(a, b, c, d, e, f2(b, c, d), x, 0x7A6D76E9, r); - }; - - private func r52( - a : Nat32, - b : Nat32, - c : Nat32, - d : Nat32, - e : Nat32, - x : Nat32, - r : Nat32, - ) : (Nat32, Nat32) { - round(a, b, c, d, e, f1(b, c, d), x, 0, r); - }; - - // Perform a RIPEMD-160 transformation, processing a 64-byte chunk. - private func transform(chunk : [Nat8], offset : Nat) { var a1 : Nat32 = s[0]; var b1 : Nat32 = s[1]; var c1 : Nat32 = s[2]; @@ -202,508 +83,188 @@ module { var c2 : Nat32 = c1; var d2 : Nat32 = d1; var e2 : Nat32 = e1; - let w0 : Nat32 = Common.readLE32(chunk, offset); - let w1 : Nat32 = Common.readLE32(chunk, offset + 4); - let w2 : Nat32 = Common.readLE32(chunk, offset + 8); - let w3 : Nat32 = Common.readLE32(chunk, offset + 12); - let w4 : Nat32 = Common.readLE32(chunk, offset + 16); - let w5 : Nat32 = Common.readLE32(chunk, offset + 20); - let w6 : Nat32 = Common.readLE32(chunk, offset + 24); - let w7 : Nat32 = Common.readLE32(chunk, offset + 28); - let w8 : Nat32 = Common.readLE32(chunk, offset + 32); - let w9 : Nat32 = Common.readLE32(chunk, offset + 36); - let w10 : Nat32 = Common.readLE32(chunk, offset + 40); - let w11 : Nat32 = Common.readLE32(chunk, offset + 44); - let w12 : Nat32 = Common.readLE32(chunk, offset + 48); - let w13 : Nat32 = Common.readLE32(chunk, offset + 52); - let w14 : Nat32 = Common.readLE32(chunk, offset + 56); - let w15 : Nat32 = Common.readLE32(chunk, offset + 60); - - var temp : (Nat32, Nat32) = r11(a1, b1, c1, d1, e1, w0, 11); - a1 := temp.0; - c1 := temp.1; - temp := r12(a2, b2, c2, d2, e2, w5, 8); - a2 := temp.0; - c2 := temp.1; - temp := r11(e1, a1, b1, c1, d1, w1, 14); - e1 := temp.0; - b1 := temp.1; - temp := r12(e2, a2, b2, c2, d2, w14, 9); - e2 := temp.0; - b2 := temp.1; - temp := r11(d1, e1, a1, b1, c1, w2, 15); - d1 := temp.0; - a1 := temp.1; - temp := r12(d2, e2, a2, b2, c2, w7, 9); - d2 := temp.0; - a2 := temp.1; - temp := r11(c1, d1, e1, a1, b1, w3, 12); - c1 := temp.0; - e1 := temp.1; - temp := r12(c2, d2, e2, a2, b2, w0, 11); - c2 := temp.0; - e2 := temp.1; - temp := r11(b1, c1, d1, e1, a1, w4, 5); - b1 := temp.0; - d1 := temp.1; - temp := r12(b2, c2, d2, e2, a2, w9, 13); - b2 := temp.0; - d2 := temp.1; - temp := r11(a1, b1, c1, d1, e1, w5, 8); - a1 := temp.0; - c1 := temp.1; - temp := r12(a2, b2, c2, d2, e2, w2, 15); - a2 := temp.0; - c2 := temp.1; - temp := r11(e1, a1, b1, c1, d1, w6, 7); - e1 := temp.0; - b1 := temp.1; - temp := r12(e2, a2, b2, c2, d2, w11, 15); - e2 := temp.0; - b2 := temp.1; - temp := r11(d1, e1, a1, b1, c1, w7, 9); - d1 := temp.0; - a1 := temp.1; - temp := r12(d2, e2, a2, b2, c2, w4, 5); - d2 := temp.0; - a2 := temp.1; - temp := r11(c1, d1, e1, a1, b1, w8, 11); - c1 := temp.0; - e1 := temp.1; - temp := r12(c2, d2, e2, a2, b2, w13, 7); - c2 := temp.0; - e2 := temp.1; - temp := r11(b1, c1, d1, e1, a1, w9, 13); - b1 := temp.0; - d1 := temp.1; - temp := r12(b2, c2, d2, e2, a2, w6, 7); - b2 := temp.0; - d2 := temp.1; - temp := r11(a1, b1, c1, d1, e1, w10, 14); - a1 := temp.0; - c1 := temp.1; - temp := r12(a2, b2, c2, d2, e2, w15, 8); - a2 := temp.0; - c2 := temp.1; - temp := r11(e1, a1, b1, c1, d1, w11, 15); - e1 := temp.0; - b1 := temp.1; - temp := r12(e2, a2, b2, c2, d2, w8, 11); - e2 := temp.0; - b2 := temp.1; - temp := r11(d1, e1, a1, b1, c1, w12, 6); - d1 := temp.0; - a1 := temp.1; - temp := r12(d2, e2, a2, b2, c2, w1, 14); - d2 := temp.0; - a2 := temp.1; - temp := r11(c1, d1, e1, a1, b1, w13, 7); - c1 := temp.0; - e1 := temp.1; - temp := r12(c2, d2, e2, a2, b2, w10, 14); - c2 := temp.0; - e2 := temp.1; - temp := r11(b1, c1, d1, e1, a1, w14, 9); - b1 := temp.0; - d1 := temp.1; - temp := r12(b2, c2, d2, e2, a2, w3, 12); - b2 := temp.0; - d2 := temp.1; - temp := r11(a1, b1, c1, d1, e1, w15, 8); - a1 := temp.0; - c1 := temp.1; - temp := r12(a2, b2, c2, d2, e2, w12, 6); - a2 := temp.0; - c2 := temp.1; - - temp := r21(e1, a1, b1, c1, d1, w7, 7); - e1 := temp.0; - b1 := temp.1; - temp := r22(e2, a2, b2, c2, d2, w6, 9); - e2 := temp.0; - b2 := temp.1; - temp := r21(d1, e1, a1, b1, c1, w4, 6); - d1 := temp.0; - a1 := temp.1; - temp := r22(d2, e2, a2, b2, c2, w11, 13); - d2 := temp.0; - a2 := temp.1; - temp := r21(c1, d1, e1, a1, b1, w13, 8); - c1 := temp.0; - e1 := temp.1; - temp := r22(c2, d2, e2, a2, b2, w3, 15); - c2 := temp.0; - e2 := temp.1; - temp := r21(b1, c1, d1, e1, a1, w1, 13); - b1 := temp.0; - d1 := temp.1; - temp := r22(b2, c2, d2, e2, a2, w7, 7); - b2 := temp.0; - d2 := temp.1; - temp := r21(a1, b1, c1, d1, e1, w10, 11); - a1 := temp.0; - c1 := temp.1; - temp := r22(a2, b2, c2, d2, e2, w0, 12); - a2 := temp.0; - c2 := temp.1; - temp := r21(e1, a1, b1, c1, d1, w6, 9); - e1 := temp.0; - b1 := temp.1; - temp := r22(e2, a2, b2, c2, d2, w13, 8); - e2 := temp.0; - b2 := temp.1; - temp := r21(d1, e1, a1, b1, c1, w15, 7); - d1 := temp.0; - a1 := temp.1; - temp := r22(d2, e2, a2, b2, c2, w5, 9); - d2 := temp.0; - a2 := temp.1; - temp := r21(c1, d1, e1, a1, b1, w3, 15); - c1 := temp.0; - e1 := temp.1; - temp := r22(c2, d2, e2, a2, b2, w10, 11); - c2 := temp.0; - e2 := temp.1; - temp := r21(b1, c1, d1, e1, a1, w12, 7); - b1 := temp.0; - d1 := temp.1; - temp := r22(b2, c2, d2, e2, a2, w14, 7); - b2 := temp.0; - d2 := temp.1; - temp := r21(a1, b1, c1, d1, e1, w0, 12); - a1 := temp.0; - c1 := temp.1; - temp := r22(a2, b2, c2, d2, e2, w15, 7); - a2 := temp.0; - c2 := temp.1; - temp := r21(e1, a1, b1, c1, d1, w9, 15); - e1 := temp.0; - b1 := temp.1; - temp := r22(e2, a2, b2, c2, d2, w8, 12); - e2 := temp.0; - b2 := temp.1; - temp := r21(d1, e1, a1, b1, c1, w5, 9); - d1 := temp.0; - a1 := temp.1; - temp := r22(d2, e2, a2, b2, c2, w12, 7); - d2 := temp.0; - a2 := temp.1; - temp := r21(c1, d1, e1, a1, b1, w2, 11); - c1 := temp.0; - e1 := temp.1; - temp := r22(c2, d2, e2, a2, b2, w4, 6); - c2 := temp.0; - e2 := temp.1; - temp := r21(b1, c1, d1, e1, a1, w14, 7); - b1 := temp.0; - d1 := temp.1; - temp := r22(b2, c2, d2, e2, a2, w9, 15); - b2 := temp.0; - d2 := temp.1; - temp := r21(a1, b1, c1, d1, e1, w11, 13); - a1 := temp.0; - c1 := temp.1; - temp := r22(a2, b2, c2, d2, e2, w1, 13); - a2 := temp.0; - c2 := temp.1; - temp := r21(e1, a1, b1, c1, d1, w8, 12); - e1 := temp.0; - b1 := temp.1; - temp := r22(e2, a2, b2, c2, d2, w2, 11); - e2 := temp.0; - b2 := temp.1; - - temp := r31(d1, e1, a1, b1, c1, w3, 11); - d1 := temp.0; - a1 := temp.1; - temp := r32(d2, e2, a2, b2, c2, w15, 9); - d2 := temp.0; - a2 := temp.1; - temp := r31(c1, d1, e1, a1, b1, w10, 13); - c1 := temp.0; - e1 := temp.1; - temp := r32(c2, d2, e2, a2, b2, w5, 7); - c2 := temp.0; - e2 := temp.1; - temp := r31(b1, c1, d1, e1, a1, w14, 6); - b1 := temp.0; - d1 := temp.1; - temp := r32(b2, c2, d2, e2, a2, w1, 15); - b2 := temp.0; - d2 := temp.1; - temp := r31(a1, b1, c1, d1, e1, w4, 7); - a1 := temp.0; - c1 := temp.1; - temp := r32(a2, b2, c2, d2, e2, w3, 11); - a2 := temp.0; - c2 := temp.1; - temp := r31(e1, a1, b1, c1, d1, w9, 14); - e1 := temp.0; - b1 := temp.1; - temp := r32(e2, a2, b2, c2, d2, w7, 8); - e2 := temp.0; - b2 := temp.1; - temp := r31(d1, e1, a1, b1, c1, w15, 9); - d1 := temp.0; - a1 := temp.1; - temp := r32(d2, e2, a2, b2, c2, w14, 6); - d2 := temp.0; - a2 := temp.1; - temp := r31(c1, d1, e1, a1, b1, w8, 13); - c1 := temp.0; - e1 := temp.1; - temp := r32(c2, d2, e2, a2, b2, w6, 6); - c2 := temp.0; - e2 := temp.1; - temp := r31(b1, c1, d1, e1, a1, w1, 15); - b1 := temp.0; - d1 := temp.1; - temp := r32(b2, c2, d2, e2, a2, w9, 14); - b2 := temp.0; - d2 := temp.1; - temp := r31(a1, b1, c1, d1, e1, w2, 14); - a1 := temp.0; - c1 := temp.1; - temp := r32(a2, b2, c2, d2, e2, w11, 12); - a2 := temp.0; - c2 := temp.1; - temp := r31(e1, a1, b1, c1, d1, w7, 8); - e1 := temp.0; - b1 := temp.1; - temp := r32(e2, a2, b2, c2, d2, w8, 13); - e2 := temp.0; - b2 := temp.1; - temp := r31(d1, e1, a1, b1, c1, w0, 13); - d1 := temp.0; - a1 := temp.1; - temp := r32(d2, e2, a2, b2, c2, w12, 5); - d2 := temp.0; - a2 := temp.1; - temp := r31(c1, d1, e1, a1, b1, w6, 6); - c1 := temp.0; - e1 := temp.1; - temp := r32(c2, d2, e2, a2, b2, w2, 14); - c2 := temp.0; - e2 := temp.1; - temp := r31(b1, c1, d1, e1, a1, w13, 5); - b1 := temp.0; - d1 := temp.1; - temp := r32(b2, c2, d2, e2, a2, w10, 13); - b2 := temp.0; - d2 := temp.1; - temp := r31(a1, b1, c1, d1, e1, w11, 12); - a1 := temp.0; - c1 := temp.1; - temp := r32(a2, b2, c2, d2, e2, w0, 13); - a2 := temp.0; - c2 := temp.1; - temp := r31(e1, a1, b1, c1, d1, w5, 7); - e1 := temp.0; - b1 := temp.1; - temp := r32(e2, a2, b2, c2, d2, w4, 7); - e2 := temp.0; - b2 := temp.1; - temp := r31(d1, e1, a1, b1, c1, w12, 5); - d1 := temp.0; - a1 := temp.1; - temp := r32(d2, e2, a2, b2, c2, w13, 5); - d2 := temp.0; - a2 := temp.1; - - temp := r41(c1, d1, e1, a1, b1, w1, 11); - c1 := temp.0; - e1 := temp.1; - temp := r42(c2, d2, e2, a2, b2, w8, 15); - c2 := temp.0; - e2 := temp.1; - temp := r41(b1, c1, d1, e1, a1, w9, 12); - b1 := temp.0; - d1 := temp.1; - temp := r42(b2, c2, d2, e2, a2, w6, 5); - b2 := temp.0; - d2 := temp.1; - temp := r41(a1, b1, c1, d1, e1, w11, 14); - a1 := temp.0; - c1 := temp.1; - temp := r42(a2, b2, c2, d2, e2, w4, 8); - a2 := temp.0; - c2 := temp.1; - temp := r41(e1, a1, b1, c1, d1, w10, 15); - e1 := temp.0; - b1 := temp.1; - temp := r42(e2, a2, b2, c2, d2, w1, 11); - e2 := temp.0; - b2 := temp.1; - temp := r41(d1, e1, a1, b1, c1, w0, 14); - d1 := temp.0; - a1 := temp.1; - temp := r42(d2, e2, a2, b2, c2, w3, 14); - d2 := temp.0; - a2 := temp.1; - temp := r41(c1, d1, e1, a1, b1, w8, 15); - c1 := temp.0; - e1 := temp.1; - temp := r42(c2, d2, e2, a2, b2, w11, 14); - c2 := temp.0; - e2 := temp.1; - temp := r41(b1, c1, d1, e1, a1, w12, 9); - b1 := temp.0; - d1 := temp.1; - temp := r42(b2, c2, d2, e2, a2, w15, 6); - b2 := temp.0; - d2 := temp.1; - temp := r41(a1, b1, c1, d1, e1, w4, 8); - a1 := temp.0; - c1 := temp.1; - temp := r42(a2, b2, c2, d2, e2, w0, 14); - a2 := temp.0; - c2 := temp.1; - temp := r41(e1, a1, b1, c1, d1, w13, 9); - e1 := temp.0; - b1 := temp.1; - temp := r42(e2, a2, b2, c2, d2, w5, 6); - e2 := temp.0; - b2 := temp.1; - temp := r41(d1, e1, a1, b1, c1, w3, 14); - d1 := temp.0; - a1 := temp.1; - temp := r42(d2, e2, a2, b2, c2, w12, 9); - d2 := temp.0; - a2 := temp.1; - temp := r41(c1, d1, e1, a1, b1, w7, 5); - c1 := temp.0; - e1 := temp.1; - temp := r42(c2, d2, e2, a2, b2, w2, 12); - c2 := temp.0; - e2 := temp.1; - temp := r41(b1, c1, d1, e1, a1, w15, 6); - b1 := temp.0; - d1 := temp.1; - temp := r42(b2, c2, d2, e2, a2, w13, 9); - b2 := temp.0; - d2 := temp.1; - temp := r41(a1, b1, c1, d1, e1, w14, 8); - a1 := temp.0; - c1 := temp.1; - temp := r42(a2, b2, c2, d2, e2, w9, 12); - a2 := temp.0; - c2 := temp.1; - temp := r41(e1, a1, b1, c1, d1, w5, 6); - e1 := temp.0; - b1 := temp.1; - temp := r42(e2, a2, b2, c2, d2, w7, 5); - e2 := temp.0; - b2 := temp.1; - temp := r41(d1, e1, a1, b1, c1, w6, 5); - d1 := temp.0; - a1 := temp.1; - temp := r42(d2, e2, a2, b2, c2, w10, 15); - d2 := temp.0; - a2 := temp.1; - temp := r41(c1, d1, e1, a1, b1, w2, 12); - c1 := temp.0; - e1 := temp.1; - temp := r42(c2, d2, e2, a2, b2, w14, 8); - c2 := temp.0; - e2 := temp.1; - - temp := r51(b1, c1, d1, e1, a1, w4, 9); - b1 := temp.0; - d1 := temp.1; - temp := r52(b2, c2, d2, e2, a2, w12, 8); - b2 := temp.0; - d2 := temp.1; - temp := r51(a1, b1, c1, d1, e1, w0, 15); - a1 := temp.0; - c1 := temp.1; - temp := r52(a2, b2, c2, d2, e2, w15, 5); - a2 := temp.0; - c2 := temp.1; - temp := r51(e1, a1, b1, c1, d1, w5, 5); - e1 := temp.0; - b1 := temp.1; - temp := r52(e2, a2, b2, c2, d2, w10, 12); - e2 := temp.0; - b2 := temp.1; - temp := r51(d1, e1, a1, b1, c1, w9, 11); - d1 := temp.0; - a1 := temp.1; - temp := r52(d2, e2, a2, b2, c2, w4, 9); - d2 := temp.0; - a2 := temp.1; - temp := r51(c1, d1, e1, a1, b1, w7, 6); - c1 := temp.0; - e1 := temp.1; - temp := r52(c2, d2, e2, a2, b2, w1, 12); - c2 := temp.0; - e2 := temp.1; - temp := r51(b1, c1, d1, e1, a1, w12, 8); - b1 := temp.0; - d1 := temp.1; - temp := r52(b2, c2, d2, e2, a2, w5, 5); - b2 := temp.0; - d2 := temp.1; - temp := r51(a1, b1, c1, d1, e1, w2, 13); - a1 := temp.0; - c1 := temp.1; - temp := r52(a2, b2, c2, d2, e2, w8, 14); - a2 := temp.0; - c2 := temp.1; - temp := r51(e1, a1, b1, c1, d1, w10, 12); - e1 := temp.0; - b1 := temp.1; - temp := r52(e2, a2, b2, c2, d2, w7, 6); - e2 := temp.0; - b2 := temp.1; - temp := r51(d1, e1, a1, b1, c1, w14, 5); - d1 := temp.0; - a1 := temp.1; - temp := r52(d2, e2, a2, b2, c2, w6, 8); - d2 := temp.0; - a2 := temp.1; - temp := r51(c1, d1, e1, a1, b1, w1, 12); - c1 := temp.0; - e1 := temp.1; - temp := r52(c2, d2, e2, a2, b2, w2, 13); - c2 := temp.0; - e2 := temp.1; - temp := r51(b1, c1, d1, e1, a1, w3, 13); - b1 := temp.0; - d1 := temp.1; - temp := r52(b2, c2, d2, e2, a2, w13, 6); - b2 := temp.0; - d2 := temp.1; - temp := r51(a1, b1, c1, d1, e1, w8, 14); - a1 := temp.0; - c1 := temp.1; - temp := r52(a2, b2, c2, d2, e2, w14, 5); - a2 := temp.0; - c2 := temp.1; - temp := r51(e1, a1, b1, c1, d1, w11, 11); - e1 := temp.0; - b1 := temp.1; - temp := r52(e2, a2, b2, c2, d2, w0, 15); - e2 := temp.0; - b2 := temp.1; - temp := r51(d1, e1, a1, b1, c1, w6, 8); - d1 := temp.0; - a1 := temp.1; - temp := r52(d2, e2, a2, b2, c2, w3, 13); - d2 := temp.0; - a2 := temp.1; - temp := r51(c1, d1, e1, a1, b1, w15, 5); - c1 := temp.0; - e1 := temp.1; - temp := r52(c2, d2, e2, a2, b2, w9, 11); - c2 := temp.0; - e2 := temp.1; - temp := r51(b1, c1, d1, e1, a1, w13, 6); - b1 := temp.0; - d1 := temp.1; - temp := r52(b2, c2, d2, e2, a2, w11, 11); - b2 := temp.0; - d2 := temp.1; + // ---- Left line round 1: f1(b,c,d) = b^c^d, K = 0 + a1 := rol(a1 +% (b1 ^ c1 ^ d1) +% w0, 11) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% (a1 ^ b1 ^ c1) +% w1, 14) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% (e1 ^ a1 ^ b1) +% w2, 15) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% (d1 ^ e1 ^ a1) +% w3, 12) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% (c1 ^ d1 ^ e1) +% w4, 5) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% (b1 ^ c1 ^ d1) +% w5, 8) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% (a1 ^ b1 ^ c1) +% w6, 7) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% (e1 ^ a1 ^ b1) +% w7, 9) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% (d1 ^ e1 ^ a1) +% w8, 11) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% (c1 ^ d1 ^ e1) +% w9, 13) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% (b1 ^ c1 ^ d1) +% w10, 14) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% (a1 ^ b1 ^ c1) +% w11, 15) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% (e1 ^ a1 ^ b1) +% w12, 6) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% (d1 ^ e1 ^ a1) +% w13, 7) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% (c1 ^ d1 ^ e1) +% w14, 9) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% (b1 ^ c1 ^ d1) +% w15, 8) +% e1; c1 := rol(c1, 10); + + // ---- Left line round 2: f2(b,c,d) = (b & c) | (~b & d), K = 0x5A827999 + e1 := rol(e1 +% ((a1 & b1) | (^a1 & c1)) +% w7 +% 0x5A827999, 7) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 & a1) | (^e1 & b1)) +% w4 +% 0x5A827999, 6) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 & e1) | (^d1 & a1)) +% w13 +% 0x5A827999, 8) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 & d1) | (^c1 & e1)) +% w1 +% 0x5A827999, 13) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 & c1) | (^b1 & d1)) +% w10 +% 0x5A827999, 11) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 & b1) | (^a1 & c1)) +% w6 +% 0x5A827999, 9) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 & a1) | (^e1 & b1)) +% w15 +% 0x5A827999, 7) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 & e1) | (^d1 & a1)) +% w3 +% 0x5A827999, 15) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 & d1) | (^c1 & e1)) +% w12 +% 0x5A827999, 7) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 & c1) | (^b1 & d1)) +% w0 +% 0x5A827999, 12) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 & b1) | (^a1 & c1)) +% w9 +% 0x5A827999, 15) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 & a1) | (^e1 & b1)) +% w5 +% 0x5A827999, 9) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 & e1) | (^d1 & a1)) +% w2 +% 0x5A827999, 11) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 & d1) | (^c1 & e1)) +% w14 +% 0x5A827999, 7) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 & c1) | (^b1 & d1)) +% w11 +% 0x5A827999, 13) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 & b1) | (^a1 & c1)) +% w8 +% 0x5A827999, 12) +% d1; b1 := rol(b1, 10); + + // ---- Left line round 3: f3(b,c,d) = (b | ~c) ^ d, K = 0x6ED9EBA1 + d1 := rol(d1 +% ((e1 | ^a1) ^ b1) +% w3 +% 0x6ED9EBA1, 11) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 | ^e1) ^ a1) +% w10 +% 0x6ED9EBA1, 13) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 | ^d1) ^ e1) +% w14 +% 0x6ED9EBA1, 6) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 | ^c1) ^ d1) +% w4 +% 0x6ED9EBA1, 7) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 | ^b1) ^ c1) +% w9 +% 0x6ED9EBA1, 14) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 | ^a1) ^ b1) +% w15 +% 0x6ED9EBA1, 9) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 | ^e1) ^ a1) +% w8 +% 0x6ED9EBA1, 13) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 | ^d1) ^ e1) +% w1 +% 0x6ED9EBA1, 15) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 | ^c1) ^ d1) +% w2 +% 0x6ED9EBA1, 14) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 | ^b1) ^ c1) +% w7 +% 0x6ED9EBA1, 8) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 | ^a1) ^ b1) +% w0 +% 0x6ED9EBA1, 13) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 | ^e1) ^ a1) +% w6 +% 0x6ED9EBA1, 6) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 | ^d1) ^ e1) +% w13 +% 0x6ED9EBA1, 5) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 | ^c1) ^ d1) +% w11 +% 0x6ED9EBA1, 12) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 | ^b1) ^ c1) +% w5 +% 0x6ED9EBA1, 7) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 | ^a1) ^ b1) +% w12 +% 0x6ED9EBA1, 5) +% c1; a1 := rol(a1, 10); + + // ---- Left line round 4: f4(b,c,d) = (b & d) | (c & ~d), K = 0x8F1BBCDC + c1 := rol(c1 +% ((d1 & a1) | (e1 & ^a1)) +% w1 +% 0x8F1BBCDC, 11) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 & e1) | (d1 & ^e1)) +% w9 +% 0x8F1BBCDC, 12) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 & d1) | (c1 & ^d1)) +% w11 +% 0x8F1BBCDC, 14) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 & c1) | (b1 & ^c1)) +% w10 +% 0x8F1BBCDC, 15) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 & b1) | (a1 & ^b1)) +% w0 +% 0x8F1BBCDC, 14) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 & a1) | (e1 & ^a1)) +% w8 +% 0x8F1BBCDC, 15) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 & e1) | (d1 & ^e1)) +% w12 +% 0x8F1BBCDC, 9) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 & d1) | (c1 & ^d1)) +% w4 +% 0x8F1BBCDC, 8) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 & c1) | (b1 & ^c1)) +% w13 +% 0x8F1BBCDC, 9) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 & b1) | (a1 & ^b1)) +% w3 +% 0x8F1BBCDC, 14) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 & a1) | (e1 & ^a1)) +% w7 +% 0x8F1BBCDC, 5) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 & e1) | (d1 & ^e1)) +% w15 +% 0x8F1BBCDC, 6) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 & d1) | (c1 & ^d1)) +% w14 +% 0x8F1BBCDC, 8) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 & c1) | (b1 & ^c1)) +% w5 +% 0x8F1BBCDC, 6) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 & b1) | (a1 & ^b1)) +% w6 +% 0x8F1BBCDC, 5) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 & a1) | (e1 & ^a1)) +% w2 +% 0x8F1BBCDC, 12) +% b1; e1 := rol(e1, 10); + + // ---- Left line round 5: f5(b,c,d) = b ^ (c | ~d), K = 0xA953FD4E + b1 := rol(b1 +% (c1 ^ (d1 | ^e1)) +% w4 +% 0xA953FD4E, 9) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% (b1 ^ (c1 | ^d1)) +% w0 +% 0xA953FD4E, 15) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% (a1 ^ (b1 | ^c1)) +% w5 +% 0xA953FD4E, 5) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% (e1 ^ (a1 | ^b1)) +% w9 +% 0xA953FD4E, 11) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% (d1 ^ (e1 | ^a1)) +% w7 +% 0xA953FD4E, 6) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% (c1 ^ (d1 | ^e1)) +% w12 +% 0xA953FD4E, 8) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% (b1 ^ (c1 | ^d1)) +% w2 +% 0xA953FD4E, 13) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% (a1 ^ (b1 | ^c1)) +% w10 +% 0xA953FD4E, 12) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% (e1 ^ (a1 | ^b1)) +% w14 +% 0xA953FD4E, 5) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% (d1 ^ (e1 | ^a1)) +% w1 +% 0xA953FD4E, 12) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% (c1 ^ (d1 | ^e1)) +% w3 +% 0xA953FD4E, 13) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% (b1 ^ (c1 | ^d1)) +% w8 +% 0xA953FD4E, 14) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% (a1 ^ (b1 | ^c1)) +% w11 +% 0xA953FD4E, 11) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% (e1 ^ (a1 | ^b1)) +% w6 +% 0xA953FD4E, 8) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% (d1 ^ (e1 | ^a1)) +% w15 +% 0xA953FD4E, 5) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% (c1 ^ (d1 | ^e1)) +% w13 +% 0xA953FD4E, 6) +% a1; d1 := rol(d1, 10); + + // ---- Right line round 1: f5, K = 0x50A28BE6 + a2 := rol(a2 +% (b2 ^ (c2 | ^d2)) +% w5 +% 0x50A28BE6, 8) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% (a2 ^ (b2 | ^c2)) +% w14 +% 0x50A28BE6, 9) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% (e2 ^ (a2 | ^b2)) +% w7 +% 0x50A28BE6, 9) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% (d2 ^ (e2 | ^a2)) +% w0 +% 0x50A28BE6, 11) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% (c2 ^ (d2 | ^e2)) +% w9 +% 0x50A28BE6, 13) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% (b2 ^ (c2 | ^d2)) +% w2 +% 0x50A28BE6, 15) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% (a2 ^ (b2 | ^c2)) +% w11 +% 0x50A28BE6, 15) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% (e2 ^ (a2 | ^b2)) +% w4 +% 0x50A28BE6, 5) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% (d2 ^ (e2 | ^a2)) +% w13 +% 0x50A28BE6, 7) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% (c2 ^ (d2 | ^e2)) +% w6 +% 0x50A28BE6, 7) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% (b2 ^ (c2 | ^d2)) +% w15 +% 0x50A28BE6, 8) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% (a2 ^ (b2 | ^c2)) +% w8 +% 0x50A28BE6, 11) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% (e2 ^ (a2 | ^b2)) +% w1 +% 0x50A28BE6, 14) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% (d2 ^ (e2 | ^a2)) +% w10 +% 0x50A28BE6, 14) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% (c2 ^ (d2 | ^e2)) +% w3 +% 0x50A28BE6, 12) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% (b2 ^ (c2 | ^d2)) +% w12 +% 0x50A28BE6, 6) +% e2; c2 := rol(c2, 10); + + // ---- Right line round 2: f4, K = 0x5C4DD124 + e2 := rol(e2 +% ((a2 & c2) | (b2 & ^c2)) +% w6 +% 0x5C4DD124, 9) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 & b2) | (a2 & ^b2)) +% w11 +% 0x5C4DD124, 13) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 & a2) | (e2 & ^a2)) +% w3 +% 0x5C4DD124, 15) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 & e2) | (d2 & ^e2)) +% w7 +% 0x5C4DD124, 7) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 & d2) | (c2 & ^d2)) +% w0 +% 0x5C4DD124, 12) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 & c2) | (b2 & ^c2)) +% w13 +% 0x5C4DD124, 8) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 & b2) | (a2 & ^b2)) +% w5 +% 0x5C4DD124, 9) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 & a2) | (e2 & ^a2)) +% w10 +% 0x5C4DD124, 11) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 & e2) | (d2 & ^e2)) +% w14 +% 0x5C4DD124, 7) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 & d2) | (c2 & ^d2)) +% w15 +% 0x5C4DD124, 7) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 & c2) | (b2 & ^c2)) +% w8 +% 0x5C4DD124, 12) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 & b2) | (a2 & ^b2)) +% w12 +% 0x5C4DD124, 7) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 & a2) | (e2 & ^a2)) +% w4 +% 0x5C4DD124, 6) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 & e2) | (d2 & ^e2)) +% w9 +% 0x5C4DD124, 15) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 & d2) | (c2 & ^d2)) +% w1 +% 0x5C4DD124, 13) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 & c2) | (b2 & ^c2)) +% w2 +% 0x5C4DD124, 11) +% d2; b2 := rol(b2, 10); + + // ---- Right line round 3: f3, K = 0x6D703EF3 + d2 := rol(d2 +% ((e2 | ^a2) ^ b2) +% w15 +% 0x6D703EF3, 9) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 | ^e2) ^ a2) +% w5 +% 0x6D703EF3, 7) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 | ^d2) ^ e2) +% w1 +% 0x6D703EF3, 15) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 | ^c2) ^ d2) +% w3 +% 0x6D703EF3, 11) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 | ^b2) ^ c2) +% w7 +% 0x6D703EF3, 8) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 | ^a2) ^ b2) +% w14 +% 0x6D703EF3, 6) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 | ^e2) ^ a2) +% w6 +% 0x6D703EF3, 6) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 | ^d2) ^ e2) +% w9 +% 0x6D703EF3, 14) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 | ^c2) ^ d2) +% w11 +% 0x6D703EF3, 12) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 | ^b2) ^ c2) +% w8 +% 0x6D703EF3, 13) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 | ^a2) ^ b2) +% w12 +% 0x6D703EF3, 5) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 | ^e2) ^ a2) +% w2 +% 0x6D703EF3, 14) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 | ^d2) ^ e2) +% w10 +% 0x6D703EF3, 13) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 | ^c2) ^ d2) +% w0 +% 0x6D703EF3, 13) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 | ^b2) ^ c2) +% w4 +% 0x6D703EF3, 7) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 | ^a2) ^ b2) +% w13 +% 0x6D703EF3, 5) +% c2; a2 := rol(a2, 10); + + // ---- Right line round 4: f2, K = 0x7A6D76E9 + c2 := rol(c2 +% ((d2 & e2) | (^d2 & a2)) +% w8 +% 0x7A6D76E9, 15) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 & d2) | (^c2 & e2)) +% w6 +% 0x7A6D76E9, 5) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 & c2) | (^b2 & d2)) +% w4 +% 0x7A6D76E9, 8) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 & b2) | (^a2 & c2)) +% w1 +% 0x7A6D76E9, 11) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 & a2) | (^e2 & b2)) +% w3 +% 0x7A6D76E9, 14) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 & e2) | (^d2 & a2)) +% w11 +% 0x7A6D76E9, 14) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 & d2) | (^c2 & e2)) +% w15 +% 0x7A6D76E9, 6) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 & c2) | (^b2 & d2)) +% w0 +% 0x7A6D76E9, 14) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 & b2) | (^a2 & c2)) +% w5 +% 0x7A6D76E9, 6) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 & a2) | (^e2 & b2)) +% w12 +% 0x7A6D76E9, 9) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 & e2) | (^d2 & a2)) +% w2 +% 0x7A6D76E9, 12) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 & d2) | (^c2 & e2)) +% w13 +% 0x7A6D76E9, 9) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 & c2) | (^b2 & d2)) +% w9 +% 0x7A6D76E9, 12) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 & b2) | (^a2 & c2)) +% w7 +% 0x7A6D76E9, 5) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 & a2) | (^e2 & b2)) +% w10 +% 0x7A6D76E9, 15) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 & e2) | (^d2 & a2)) +% w14 +% 0x7A6D76E9, 8) +% b2; e2 := rol(e2, 10); + + // ---- Right line round 5: f1, K = 0 + b2 := rol(b2 +% (c2 ^ d2 ^ e2) +% w12, 8) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% (b2 ^ c2 ^ d2) +% w15, 5) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% (a2 ^ b2 ^ c2) +% w10, 12) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% (e2 ^ a2 ^ b2) +% w4, 9) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% (d2 ^ e2 ^ a2) +% w1, 12) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% (c2 ^ d2 ^ e2) +% w5, 5) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% (b2 ^ c2 ^ d2) +% w8, 14) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% (a2 ^ b2 ^ c2) +% w7, 6) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% (e2 ^ a2 ^ b2) +% w6, 8) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% (d2 ^ e2 ^ a2) +% w2, 13) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% (c2 ^ d2 ^ e2) +% w13, 6) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% (b2 ^ c2 ^ d2) +% w14, 5) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% (a2 ^ b2 ^ c2) +% w0, 15) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% (e2 ^ a2 ^ b2) +% w3, 13) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% (d2 ^ e2 ^ a2) +% w9, 11) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% (c2 ^ d2 ^ e2) +% w11, 11) +% a2; d2 := rol(d2, 10); + + // Combine the two lines back into the chaining state. let t : Nat32 = s[0]; s[0] := s[1] +% c1 +% d2; s[1] := s[2] +% d1 +% e2; @@ -712,62 +273,112 @@ module { s[4] := t +% b1 +% c2; }; - public func write(data : [Nat8]) { - var bufsize : Nat = (bytes % 64).toNat(); - var transformOffset : Nat = 0; - - // Check if the incoming data is enough to fill the buffer - // which might have data from a previous call. - if (bufsize > 0 and (bufsize + data.size() >= 64)) { - // Fill the buffer, and process it. - for (i in Nat.range(bufsize, 64)) { - buf[i] := data[i - bufsize]; - }; - // Add the count of processed bytes. - bytes += 64 - Nat64.fromNat(bufsize); - transform(buf.toArray(), 0); - // All data in the buffer has been processed, reset buffer data size - // point transformOffset to index of not-yet processed data. - transformOffset += 64 - bufsize; - bufsize := 0; + // Append a single byte to the current block, processing the block when + // it becomes full. The byte is folded into msg[i_msg >> 2] at the + // little-endian position implied by (i_msg & 3). + private func writeByte(b : Nat8) { + let pos = i_msg; + let wi = Nat16.toNat(pos >> 2); + let lane = pos & 0x3; + let v : Nat32 = Nat32.fromNat16(b.toNat16()) << Nat32.fromNat16(lane << 3); + if (lane == 0) { + // First byte of a fresh word: overwrite (the slot may carry stale + // data from an earlier block, since we never explicitly clear msg). + msg[wi] := v; + } else { + msg[wi] := msg[wi] | v; }; - // If size of not-yet processed incoming data fits in buffer, - // process it. - while (data.size() >= transformOffset + 64) { - // Process full chunks directly from the source. - transform(data, transformOffset); - // Add the count of processed bytes. - bytes += 64; - transformOffset += 64; - }; - // Push any not-yet processed data to buffer. - for (i in Nat.range(transformOffset, data.size())) { - buf[bufsize + i - transformOffset] := data[i]; - bytes += 1; + let next = pos +% 1; + if (next == 64) { + transform(); + n_blocks +%= 1; + i_msg := 0; + } else { + i_msg := next; }; }; - public func sum() : [Nat8] { - let pad : [var Nat8] = VarArray.repeat( - 0, - (1 + ((119 - (bytes % 64)) % 64)).toNat(), - ); - pad[0] := 0x80; + public func write(data : [Nat8]) { + let n = data.size(); + if (n == 0) return; + var i = 0; + + // 1) If a partial block is in progress, fill it byte by byte. + while (i_msg != 0 and i < n) { + writeByte(data[i]); + i += 1; + }; - let sizedesc : [var Nat8] = VarArray.repeat(0, 8); - Common.writeLE64(sizedesc, 0, bytes << 3); + // 2) Fast path: process any number of full 64-byte blocks directly, + // decoding 16 little-endian words inline into msg per block. + while (i + 64 <= n) { + msg[0] := data[i].toNat16().toNat32() | (data[i+1].toNat16().toNat32() << 8) | (data[i+2].toNat16().toNat32() << 16) | (data[i+3].toNat16().toNat32() << 24); + msg[1] := data[i+4].toNat16().toNat32() | (data[i+5].toNat16().toNat32() << 8) | (data[i+6].toNat16().toNat32() << 16) | (data[i+7].toNat16().toNat32() << 24); + msg[2] := data[i+8].toNat16().toNat32() | (data[i+9].toNat16().toNat32() << 8) | (data[i+10].toNat16().toNat32() << 16) | (data[i+11].toNat16().toNat32() << 24); + msg[3] := data[i+12].toNat16().toNat32() | (data[i+13].toNat16().toNat32() << 8) | (data[i+14].toNat16().toNat32() << 16) | (data[i+15].toNat16().toNat32() << 24); + msg[4] := data[i+16].toNat16().toNat32() | (data[i+17].toNat16().toNat32() << 8) | (data[i+18].toNat16().toNat32() << 16) | (data[i+19].toNat16().toNat32() << 24); + msg[5] := data[i+20].toNat16().toNat32() | (data[i+21].toNat16().toNat32() << 8) | (data[i+22].toNat16().toNat32() << 16) | (data[i+23].toNat16().toNat32() << 24); + msg[6] := data[i+24].toNat16().toNat32() | (data[i+25].toNat16().toNat32() << 8) | (data[i+26].toNat16().toNat32() << 16) | (data[i+27].toNat16().toNat32() << 24); + msg[7] := data[i+28].toNat16().toNat32() | (data[i+29].toNat16().toNat32() << 8) | (data[i+30].toNat16().toNat32() << 16) | (data[i+31].toNat16().toNat32() << 24); + msg[8] := data[i+32].toNat16().toNat32() | (data[i+33].toNat16().toNat32() << 8) | (data[i+34].toNat16().toNat32() << 16) | (data[i+35].toNat16().toNat32() << 24); + msg[9] := data[i+36].toNat16().toNat32() | (data[i+37].toNat16().toNat32() << 8) | (data[i+38].toNat16().toNat32() << 16) | (data[i+39].toNat16().toNat32() << 24); + msg[10] := data[i+40].toNat16().toNat32() | (data[i+41].toNat16().toNat32() << 8) | (data[i+42].toNat16().toNat32() << 16) | (data[i+43].toNat16().toNat32() << 24); + msg[11] := data[i+44].toNat16().toNat32() | (data[i+45].toNat16().toNat32() << 8) | (data[i+46].toNat16().toNat32() << 16) | (data[i+47].toNat16().toNat32() << 24); + msg[12] := data[i+48].toNat16().toNat32() | (data[i+49].toNat16().toNat32() << 8) | (data[i+50].toNat16().toNat32() << 16) | (data[i+51].toNat16().toNat32() << 24); + msg[13] := data[i+52].toNat16().toNat32() | (data[i+53].toNat16().toNat32() << 8) | (data[i+54].toNat16().toNat32() << 16) | (data[i+55].toNat16().toNat32() << 24); + msg[14] := data[i+56].toNat16().toNat32() | (data[i+57].toNat16().toNat32() << 8) | (data[i+58].toNat16().toNat32() << 16) | (data[i+59].toNat16().toNat32() << 24); + msg[15] := data[i+60].toNat16().toNat32() | (data[i+61].toNat16().toNat32() << 8) | (data[i+62].toNat16().toNat32() << 16) | (data[i+63].toNat16().toNat32() << 24); + transform(); + n_blocks +%= 1; + i += 64; + }; - write(pad.toArray()); - write(sizedesc.toArray()); + // 3) Tail: copy remaining bytes one at a time into the partial block. + while (i < n) { + writeByte(data[i]); + i += 1; + }; + }; - let hash : [var Nat8] = VarArray.repeat(0, 20); - Common.writeLE32(hash, 0, s[0]); - Common.writeLE32(hash, 4, s[1]); - Common.writeLE32(hash, 8, s[2]); - Common.writeLE32(hash, 12, s[3]); - Common.writeLE32(hash, 16, s[4]); + // Convert a 64-bit value's low byte to Nat8 without going through Nat + // (avoids arbitrary-precision allocation in the padding path). + private func lowByte64(v : Nat64) : Nat8 { + Nat8.fromNat16(Nat16.fromNat32(Nat32.fromNat64(v & 0xff))); + }; - hash.toArray(); + public func sum() : [Nat8] { + // Total message length in bits, captured before padding is appended. + let bitlen : Nat64 = ((n_blocks << 6) +% Nat64.fromNat(Nat16.toNat(i_msg))) << 3; + + // Standard MD-style padding: 0x80 byte, then zeros until 56 bytes + // remain in the current block, then 8 bytes of bit length (LE). + writeByte(0x80); + while (i_msg != 56) { + writeByte(0); + }; + writeByte(lowByte64(bitlen)); + writeByte(lowByte64(bitlen >> 8)); + writeByte(lowByte64(bitlen >> 16)); + writeByte(lowByte64(bitlen >> 24)); + writeByte(lowByte64(bitlen >> 32)); + writeByte(lowByte64(bitlen >> 40)); + writeByte(lowByte64(bitlen >> 48)); + writeByte(lowByte64(bitlen >> 56)); + // The 8th length byte fills the block, triggering transform(). + + // Serialize the 5 chaining words as 20 little-endian bytes. + let out : [var Nat8] = VarArray.repeat(0, 20); + var k = 0; + while (k < 5) { + let v = s[k]; + let o = k * 4; + out[o] := Nat8.fromNat16(Nat16.fromNat32(v & 0xff)); + out[o + 1] := Nat8.fromNat16(Nat16.fromNat32((v >> 8) & 0xff)); + out[o + 2] := Nat8.fromNat16(Nat16.fromNat32((v >> 16) & 0xff)); + out[o + 3] := Nat8.fromNat16(Nat16.fromNat32((v >> 24) & 0xff)); + k += 1; + }; + out.toArray(); }; }; }; From a26063a2a77f13f9c1781a7eb0e3464177fb73b0 Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Thu, 23 Apr 2026 14:12:32 +0200 Subject: [PATCH 03/17] Use dot-notation --- src/Ripemd160.mo | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Ripemd160.mo b/src/Ripemd160.mo index 803d477..fd44086 100644 --- a/src/Ripemd160.mo +++ b/src/Ripemd160.mo @@ -280,7 +280,7 @@ module { let pos = i_msg; let wi = Nat16.toNat(pos >> 2); let lane = pos & 0x3; - let v : Nat32 = Nat32.fromNat16(b.toNat16()) << Nat32.fromNat16(lane << 3); + let v : Nat32 = b.toNat16().toNat32() << Nat32.fromNat16(lane << 3); if (lane == 0) { // First byte of a fresh word: overwrite (the slot may carry stale // data from an earlier block, since we never explicitly clear msg). @@ -343,7 +343,7 @@ module { // Convert a 64-bit value's low byte to Nat8 without going through Nat // (avoids arbitrary-precision allocation in the padding path). private func lowByte64(v : Nat64) : Nat8 { - Nat8.fromNat16(Nat16.fromNat32(Nat32.fromNat64(v & 0xff))); + (v & 0xff).toNat32().toNat16().toNat8(); }; public func sum() : [Nat8] { @@ -372,10 +372,10 @@ module { while (k < 5) { let v = s[k]; let o = k * 4; - out[o] := Nat8.fromNat16(Nat16.fromNat32(v & 0xff)); - out[o + 1] := Nat8.fromNat16(Nat16.fromNat32((v >> 8) & 0xff)); - out[o + 2] := Nat8.fromNat16(Nat16.fromNat32((v >> 16) & 0xff)); - out[o + 3] := Nat8.fromNat16(Nat16.fromNat32((v >> 24) & 0xff)); + out[o] := (v & 0xff).toNat16().toNat8(); + out[o + 1] := ((v >> 8) & 0xff).toNat16().toNat8(); + out[o + 2] := ((v >> 16) & 0xff).toNat16().toNat8(); + out[o + 3] := ((v >> 24) & 0xff).toNat16().toNat8(); k += 1; }; out.toArray(); From c718177f6136d2c2ed8edff5e1fea945873808fc Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Thu, 23 Apr 2026 14:23:16 +0200 Subject: [PATCH 04/17] Format Ripemd160.mo --- src/Ripemd160.mo | 346 ++++++++++++++++++++++++----------------------- 1 file changed, 175 insertions(+), 171 deletions(-) diff --git a/src/Ripemd160.mo b/src/Ripemd160.mo index fd44086..ca3e0a0 100644 --- a/src/Ripemd160.mo +++ b/src/Ripemd160.mo @@ -84,185 +84,188 @@ module { var d2 : Nat32 = d1; var e2 : Nat32 = e1; - // ---- Left line round 1: f1(b,c,d) = b^c^d, K = 0 - a1 := rol(a1 +% (b1 ^ c1 ^ d1) +% w0, 11) +% e1; c1 := rol(c1, 10); - e1 := rol(e1 +% (a1 ^ b1 ^ c1) +% w1, 14) +% d1; b1 := rol(b1, 10); - d1 := rol(d1 +% (e1 ^ a1 ^ b1) +% w2, 15) +% c1; a1 := rol(a1, 10); - c1 := rol(c1 +% (d1 ^ e1 ^ a1) +% w3, 12) +% b1; e1 := rol(e1, 10); - b1 := rol(b1 +% (c1 ^ d1 ^ e1) +% w4, 5) +% a1; d1 := rol(d1, 10); - a1 := rol(a1 +% (b1 ^ c1 ^ d1) +% w5, 8) +% e1; c1 := rol(c1, 10); - e1 := rol(e1 +% (a1 ^ b1 ^ c1) +% w6, 7) +% d1; b1 := rol(b1, 10); - d1 := rol(d1 +% (e1 ^ a1 ^ b1) +% w7, 9) +% c1; a1 := rol(a1, 10); - c1 := rol(c1 +% (d1 ^ e1 ^ a1) +% w8, 11) +% b1; e1 := rol(e1, 10); - b1 := rol(b1 +% (c1 ^ d1 ^ e1) +% w9, 13) +% a1; d1 := rol(d1, 10); - a1 := rol(a1 +% (b1 ^ c1 ^ d1) +% w10, 14) +% e1; c1 := rol(c1, 10); - e1 := rol(e1 +% (a1 ^ b1 ^ c1) +% w11, 15) +% d1; b1 := rol(b1, 10); - d1 := rol(d1 +% (e1 ^ a1 ^ b1) +% w12, 6) +% c1; a1 := rol(a1, 10); - c1 := rol(c1 +% (d1 ^ e1 ^ a1) +% w13, 7) +% b1; e1 := rol(e1, 10); - b1 := rol(b1 +% (c1 ^ d1 ^ e1) +% w14, 9) +% a1; d1 := rol(d1, 10); - a1 := rol(a1 +% (b1 ^ c1 ^ d1) +% w15, 8) +% e1; c1 := rol(c1, 10); + // prettier-ignore + do { + // ---- Left line round 1: f1(b,c,d) = b^c^d, K = 0 + a1 := rol(a1 +% (b1 ^ c1 ^ d1) +% w0, 11) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% (a1 ^ b1 ^ c1) +% w1, 14) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% (e1 ^ a1 ^ b1) +% w2, 15) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% (d1 ^ e1 ^ a1) +% w3, 12) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% (c1 ^ d1 ^ e1) +% w4, 5) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% (b1 ^ c1 ^ d1) +% w5, 8) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% (a1 ^ b1 ^ c1) +% w6, 7) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% (e1 ^ a1 ^ b1) +% w7, 9) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% (d1 ^ e1 ^ a1) +% w8, 11) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% (c1 ^ d1 ^ e1) +% w9, 13) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% (b1 ^ c1 ^ d1) +% w10, 14) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% (a1 ^ b1 ^ c1) +% w11, 15) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% (e1 ^ a1 ^ b1) +% w12, 6) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% (d1 ^ e1 ^ a1) +% w13, 7) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% (c1 ^ d1 ^ e1) +% w14, 9) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% (b1 ^ c1 ^ d1) +% w15, 8) +% e1; c1 := rol(c1, 10); - // ---- Left line round 2: f2(b,c,d) = (b & c) | (~b & d), K = 0x5A827999 - e1 := rol(e1 +% ((a1 & b1) | (^a1 & c1)) +% w7 +% 0x5A827999, 7) +% d1; b1 := rol(b1, 10); - d1 := rol(d1 +% ((e1 & a1) | (^e1 & b1)) +% w4 +% 0x5A827999, 6) +% c1; a1 := rol(a1, 10); - c1 := rol(c1 +% ((d1 & e1) | (^d1 & a1)) +% w13 +% 0x5A827999, 8) +% b1; e1 := rol(e1, 10); - b1 := rol(b1 +% ((c1 & d1) | (^c1 & e1)) +% w1 +% 0x5A827999, 13) +% a1; d1 := rol(d1, 10); - a1 := rol(a1 +% ((b1 & c1) | (^b1 & d1)) +% w10 +% 0x5A827999, 11) +% e1; c1 := rol(c1, 10); - e1 := rol(e1 +% ((a1 & b1) | (^a1 & c1)) +% w6 +% 0x5A827999, 9) +% d1; b1 := rol(b1, 10); - d1 := rol(d1 +% ((e1 & a1) | (^e1 & b1)) +% w15 +% 0x5A827999, 7) +% c1; a1 := rol(a1, 10); - c1 := rol(c1 +% ((d1 & e1) | (^d1 & a1)) +% w3 +% 0x5A827999, 15) +% b1; e1 := rol(e1, 10); - b1 := rol(b1 +% ((c1 & d1) | (^c1 & e1)) +% w12 +% 0x5A827999, 7) +% a1; d1 := rol(d1, 10); - a1 := rol(a1 +% ((b1 & c1) | (^b1 & d1)) +% w0 +% 0x5A827999, 12) +% e1; c1 := rol(c1, 10); - e1 := rol(e1 +% ((a1 & b1) | (^a1 & c1)) +% w9 +% 0x5A827999, 15) +% d1; b1 := rol(b1, 10); - d1 := rol(d1 +% ((e1 & a1) | (^e1 & b1)) +% w5 +% 0x5A827999, 9) +% c1; a1 := rol(a1, 10); - c1 := rol(c1 +% ((d1 & e1) | (^d1 & a1)) +% w2 +% 0x5A827999, 11) +% b1; e1 := rol(e1, 10); - b1 := rol(b1 +% ((c1 & d1) | (^c1 & e1)) +% w14 +% 0x5A827999, 7) +% a1; d1 := rol(d1, 10); - a1 := rol(a1 +% ((b1 & c1) | (^b1 & d1)) +% w11 +% 0x5A827999, 13) +% e1; c1 := rol(c1, 10); - e1 := rol(e1 +% ((a1 & b1) | (^a1 & c1)) +% w8 +% 0x5A827999, 12) +% d1; b1 := rol(b1, 10); + // ---- Left line round 2: f2(b,c,d) = (b & c) | (~b & d), K = 0x5A827999 + e1 := rol(e1 +% ((a1 & b1) | (^a1 & c1)) +% w7 +% 0x5A827999, 7) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 & a1) | (^e1 & b1)) +% w4 +% 0x5A827999, 6) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 & e1) | (^d1 & a1)) +% w13 +% 0x5A827999, 8) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 & d1) | (^c1 & e1)) +% w1 +% 0x5A827999, 13) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 & c1) | (^b1 & d1)) +% w10 +% 0x5A827999, 11) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 & b1) | (^a1 & c1)) +% w6 +% 0x5A827999, 9) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 & a1) | (^e1 & b1)) +% w15 +% 0x5A827999, 7) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 & e1) | (^d1 & a1)) +% w3 +% 0x5A827999, 15) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 & d1) | (^c1 & e1)) +% w12 +% 0x5A827999, 7) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 & c1) | (^b1 & d1)) +% w0 +% 0x5A827999, 12) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 & b1) | (^a1 & c1)) +% w9 +% 0x5A827999, 15) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 & a1) | (^e1 & b1)) +% w5 +% 0x5A827999, 9) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 & e1) | (^d1 & a1)) +% w2 +% 0x5A827999, 11) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 & d1) | (^c1 & e1)) +% w14 +% 0x5A827999, 7) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 & c1) | (^b1 & d1)) +% w11 +% 0x5A827999, 13) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 & b1) | (^a1 & c1)) +% w8 +% 0x5A827999, 12) +% d1; b1 := rol(b1, 10); - // ---- Left line round 3: f3(b,c,d) = (b | ~c) ^ d, K = 0x6ED9EBA1 - d1 := rol(d1 +% ((e1 | ^a1) ^ b1) +% w3 +% 0x6ED9EBA1, 11) +% c1; a1 := rol(a1, 10); - c1 := rol(c1 +% ((d1 | ^e1) ^ a1) +% w10 +% 0x6ED9EBA1, 13) +% b1; e1 := rol(e1, 10); - b1 := rol(b1 +% ((c1 | ^d1) ^ e1) +% w14 +% 0x6ED9EBA1, 6) +% a1; d1 := rol(d1, 10); - a1 := rol(a1 +% ((b1 | ^c1) ^ d1) +% w4 +% 0x6ED9EBA1, 7) +% e1; c1 := rol(c1, 10); - e1 := rol(e1 +% ((a1 | ^b1) ^ c1) +% w9 +% 0x6ED9EBA1, 14) +% d1; b1 := rol(b1, 10); - d1 := rol(d1 +% ((e1 | ^a1) ^ b1) +% w15 +% 0x6ED9EBA1, 9) +% c1; a1 := rol(a1, 10); - c1 := rol(c1 +% ((d1 | ^e1) ^ a1) +% w8 +% 0x6ED9EBA1, 13) +% b1; e1 := rol(e1, 10); - b1 := rol(b1 +% ((c1 | ^d1) ^ e1) +% w1 +% 0x6ED9EBA1, 15) +% a1; d1 := rol(d1, 10); - a1 := rol(a1 +% ((b1 | ^c1) ^ d1) +% w2 +% 0x6ED9EBA1, 14) +% e1; c1 := rol(c1, 10); - e1 := rol(e1 +% ((a1 | ^b1) ^ c1) +% w7 +% 0x6ED9EBA1, 8) +% d1; b1 := rol(b1, 10); - d1 := rol(d1 +% ((e1 | ^a1) ^ b1) +% w0 +% 0x6ED9EBA1, 13) +% c1; a1 := rol(a1, 10); - c1 := rol(c1 +% ((d1 | ^e1) ^ a1) +% w6 +% 0x6ED9EBA1, 6) +% b1; e1 := rol(e1, 10); - b1 := rol(b1 +% ((c1 | ^d1) ^ e1) +% w13 +% 0x6ED9EBA1, 5) +% a1; d1 := rol(d1, 10); - a1 := rol(a1 +% ((b1 | ^c1) ^ d1) +% w11 +% 0x6ED9EBA1, 12) +% e1; c1 := rol(c1, 10); - e1 := rol(e1 +% ((a1 | ^b1) ^ c1) +% w5 +% 0x6ED9EBA1, 7) +% d1; b1 := rol(b1, 10); - d1 := rol(d1 +% ((e1 | ^a1) ^ b1) +% w12 +% 0x6ED9EBA1, 5) +% c1; a1 := rol(a1, 10); + // ---- Left line round 3: f3(b,c,d) = (b | ~c) ^ d, K = 0x6ED9EBA1 + d1 := rol(d1 +% ((e1 | ^a1) ^ b1) +% w3 +% 0x6ED9EBA1, 11) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 | ^e1) ^ a1) +% w10 +% 0x6ED9EBA1, 13) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 | ^d1) ^ e1) +% w14 +% 0x6ED9EBA1, 6) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 | ^c1) ^ d1) +% w4 +% 0x6ED9EBA1, 7) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 | ^b1) ^ c1) +% w9 +% 0x6ED9EBA1, 14) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 | ^a1) ^ b1) +% w15 +% 0x6ED9EBA1, 9) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 | ^e1) ^ a1) +% w8 +% 0x6ED9EBA1, 13) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 | ^d1) ^ e1) +% w1 +% 0x6ED9EBA1, 15) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 | ^c1) ^ d1) +% w2 +% 0x6ED9EBA1, 14) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 | ^b1) ^ c1) +% w7 +% 0x6ED9EBA1, 8) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 | ^a1) ^ b1) +% w0 +% 0x6ED9EBA1, 13) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 | ^e1) ^ a1) +% w6 +% 0x6ED9EBA1, 6) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 | ^d1) ^ e1) +% w13 +% 0x6ED9EBA1, 5) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 | ^c1) ^ d1) +% w11 +% 0x6ED9EBA1, 12) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 | ^b1) ^ c1) +% w5 +% 0x6ED9EBA1, 7) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 | ^a1) ^ b1) +% w12 +% 0x6ED9EBA1, 5) +% c1; a1 := rol(a1, 10); - // ---- Left line round 4: f4(b,c,d) = (b & d) | (c & ~d), K = 0x8F1BBCDC - c1 := rol(c1 +% ((d1 & a1) | (e1 & ^a1)) +% w1 +% 0x8F1BBCDC, 11) +% b1; e1 := rol(e1, 10); - b1 := rol(b1 +% ((c1 & e1) | (d1 & ^e1)) +% w9 +% 0x8F1BBCDC, 12) +% a1; d1 := rol(d1, 10); - a1 := rol(a1 +% ((b1 & d1) | (c1 & ^d1)) +% w11 +% 0x8F1BBCDC, 14) +% e1; c1 := rol(c1, 10); - e1 := rol(e1 +% ((a1 & c1) | (b1 & ^c1)) +% w10 +% 0x8F1BBCDC, 15) +% d1; b1 := rol(b1, 10); - d1 := rol(d1 +% ((e1 & b1) | (a1 & ^b1)) +% w0 +% 0x8F1BBCDC, 14) +% c1; a1 := rol(a1, 10); - c1 := rol(c1 +% ((d1 & a1) | (e1 & ^a1)) +% w8 +% 0x8F1BBCDC, 15) +% b1; e1 := rol(e1, 10); - b1 := rol(b1 +% ((c1 & e1) | (d1 & ^e1)) +% w12 +% 0x8F1BBCDC, 9) +% a1; d1 := rol(d1, 10); - a1 := rol(a1 +% ((b1 & d1) | (c1 & ^d1)) +% w4 +% 0x8F1BBCDC, 8) +% e1; c1 := rol(c1, 10); - e1 := rol(e1 +% ((a1 & c1) | (b1 & ^c1)) +% w13 +% 0x8F1BBCDC, 9) +% d1; b1 := rol(b1, 10); - d1 := rol(d1 +% ((e1 & b1) | (a1 & ^b1)) +% w3 +% 0x8F1BBCDC, 14) +% c1; a1 := rol(a1, 10); - c1 := rol(c1 +% ((d1 & a1) | (e1 & ^a1)) +% w7 +% 0x8F1BBCDC, 5) +% b1; e1 := rol(e1, 10); - b1 := rol(b1 +% ((c1 & e1) | (d1 & ^e1)) +% w15 +% 0x8F1BBCDC, 6) +% a1; d1 := rol(d1, 10); - a1 := rol(a1 +% ((b1 & d1) | (c1 & ^d1)) +% w14 +% 0x8F1BBCDC, 8) +% e1; c1 := rol(c1, 10); - e1 := rol(e1 +% ((a1 & c1) | (b1 & ^c1)) +% w5 +% 0x8F1BBCDC, 6) +% d1; b1 := rol(b1, 10); - d1 := rol(d1 +% ((e1 & b1) | (a1 & ^b1)) +% w6 +% 0x8F1BBCDC, 5) +% c1; a1 := rol(a1, 10); - c1 := rol(c1 +% ((d1 & a1) | (e1 & ^a1)) +% w2 +% 0x8F1BBCDC, 12) +% b1; e1 := rol(e1, 10); + // ---- Left line round 4: f4(b,c,d) = (b & d) | (c & ~d), K = 0x8F1BBCDC + c1 := rol(c1 +% ((d1 & a1) | (e1 & ^a1)) +% w1 +% 0x8F1BBCDC, 11) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 & e1) | (d1 & ^e1)) +% w9 +% 0x8F1BBCDC, 12) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 & d1) | (c1 & ^d1)) +% w11 +% 0x8F1BBCDC, 14) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 & c1) | (b1 & ^c1)) +% w10 +% 0x8F1BBCDC, 15) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 & b1) | (a1 & ^b1)) +% w0 +% 0x8F1BBCDC, 14) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 & a1) | (e1 & ^a1)) +% w8 +% 0x8F1BBCDC, 15) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 & e1) | (d1 & ^e1)) +% w12 +% 0x8F1BBCDC, 9) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 & d1) | (c1 & ^d1)) +% w4 +% 0x8F1BBCDC, 8) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 & c1) | (b1 & ^c1)) +% w13 +% 0x8F1BBCDC, 9) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 & b1) | (a1 & ^b1)) +% w3 +% 0x8F1BBCDC, 14) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 & a1) | (e1 & ^a1)) +% w7 +% 0x8F1BBCDC, 5) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% ((c1 & e1) | (d1 & ^e1)) +% w15 +% 0x8F1BBCDC, 6) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% ((b1 & d1) | (c1 & ^d1)) +% w14 +% 0x8F1BBCDC, 8) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% ((a1 & c1) | (b1 & ^c1)) +% w5 +% 0x8F1BBCDC, 6) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% ((e1 & b1) | (a1 & ^b1)) +% w6 +% 0x8F1BBCDC, 5) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% ((d1 & a1) | (e1 & ^a1)) +% w2 +% 0x8F1BBCDC, 12) +% b1; e1 := rol(e1, 10); - // ---- Left line round 5: f5(b,c,d) = b ^ (c | ~d), K = 0xA953FD4E - b1 := rol(b1 +% (c1 ^ (d1 | ^e1)) +% w4 +% 0xA953FD4E, 9) +% a1; d1 := rol(d1, 10); - a1 := rol(a1 +% (b1 ^ (c1 | ^d1)) +% w0 +% 0xA953FD4E, 15) +% e1; c1 := rol(c1, 10); - e1 := rol(e1 +% (a1 ^ (b1 | ^c1)) +% w5 +% 0xA953FD4E, 5) +% d1; b1 := rol(b1, 10); - d1 := rol(d1 +% (e1 ^ (a1 | ^b1)) +% w9 +% 0xA953FD4E, 11) +% c1; a1 := rol(a1, 10); - c1 := rol(c1 +% (d1 ^ (e1 | ^a1)) +% w7 +% 0xA953FD4E, 6) +% b1; e1 := rol(e1, 10); - b1 := rol(b1 +% (c1 ^ (d1 | ^e1)) +% w12 +% 0xA953FD4E, 8) +% a1; d1 := rol(d1, 10); - a1 := rol(a1 +% (b1 ^ (c1 | ^d1)) +% w2 +% 0xA953FD4E, 13) +% e1; c1 := rol(c1, 10); - e1 := rol(e1 +% (a1 ^ (b1 | ^c1)) +% w10 +% 0xA953FD4E, 12) +% d1; b1 := rol(b1, 10); - d1 := rol(d1 +% (e1 ^ (a1 | ^b1)) +% w14 +% 0xA953FD4E, 5) +% c1; a1 := rol(a1, 10); - c1 := rol(c1 +% (d1 ^ (e1 | ^a1)) +% w1 +% 0xA953FD4E, 12) +% b1; e1 := rol(e1, 10); - b1 := rol(b1 +% (c1 ^ (d1 | ^e1)) +% w3 +% 0xA953FD4E, 13) +% a1; d1 := rol(d1, 10); - a1 := rol(a1 +% (b1 ^ (c1 | ^d1)) +% w8 +% 0xA953FD4E, 14) +% e1; c1 := rol(c1, 10); - e1 := rol(e1 +% (a1 ^ (b1 | ^c1)) +% w11 +% 0xA953FD4E, 11) +% d1; b1 := rol(b1, 10); - d1 := rol(d1 +% (e1 ^ (a1 | ^b1)) +% w6 +% 0xA953FD4E, 8) +% c1; a1 := rol(a1, 10); - c1 := rol(c1 +% (d1 ^ (e1 | ^a1)) +% w15 +% 0xA953FD4E, 5) +% b1; e1 := rol(e1, 10); - b1 := rol(b1 +% (c1 ^ (d1 | ^e1)) +% w13 +% 0xA953FD4E, 6) +% a1; d1 := rol(d1, 10); + // ---- Left line round 5: f5(b,c,d) = b ^ (c | ~d), K = 0xA953FD4E + b1 := rol(b1 +% (c1 ^ (d1 | ^e1)) +% w4 +% 0xA953FD4E, 9) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% (b1 ^ (c1 | ^d1)) +% w0 +% 0xA953FD4E, 15) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% (a1 ^ (b1 | ^c1)) +% w5 +% 0xA953FD4E, 5) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% (e1 ^ (a1 | ^b1)) +% w9 +% 0xA953FD4E, 11) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% (d1 ^ (e1 | ^a1)) +% w7 +% 0xA953FD4E, 6) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% (c1 ^ (d1 | ^e1)) +% w12 +% 0xA953FD4E, 8) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% (b1 ^ (c1 | ^d1)) +% w2 +% 0xA953FD4E, 13) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% (a1 ^ (b1 | ^c1)) +% w10 +% 0xA953FD4E, 12) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% (e1 ^ (a1 | ^b1)) +% w14 +% 0xA953FD4E, 5) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% (d1 ^ (e1 | ^a1)) +% w1 +% 0xA953FD4E, 12) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% (c1 ^ (d1 | ^e1)) +% w3 +% 0xA953FD4E, 13) +% a1; d1 := rol(d1, 10); + a1 := rol(a1 +% (b1 ^ (c1 | ^d1)) +% w8 +% 0xA953FD4E, 14) +% e1; c1 := rol(c1, 10); + e1 := rol(e1 +% (a1 ^ (b1 | ^c1)) +% w11 +% 0xA953FD4E, 11) +% d1; b1 := rol(b1, 10); + d1 := rol(d1 +% (e1 ^ (a1 | ^b1)) +% w6 +% 0xA953FD4E, 8) +% c1; a1 := rol(a1, 10); + c1 := rol(c1 +% (d1 ^ (e1 | ^a1)) +% w15 +% 0xA953FD4E, 5) +% b1; e1 := rol(e1, 10); + b1 := rol(b1 +% (c1 ^ (d1 | ^e1)) +% w13 +% 0xA953FD4E, 6) +% a1; d1 := rol(d1, 10); - // ---- Right line round 1: f5, K = 0x50A28BE6 - a2 := rol(a2 +% (b2 ^ (c2 | ^d2)) +% w5 +% 0x50A28BE6, 8) +% e2; c2 := rol(c2, 10); - e2 := rol(e2 +% (a2 ^ (b2 | ^c2)) +% w14 +% 0x50A28BE6, 9) +% d2; b2 := rol(b2, 10); - d2 := rol(d2 +% (e2 ^ (a2 | ^b2)) +% w7 +% 0x50A28BE6, 9) +% c2; a2 := rol(a2, 10); - c2 := rol(c2 +% (d2 ^ (e2 | ^a2)) +% w0 +% 0x50A28BE6, 11) +% b2; e2 := rol(e2, 10); - b2 := rol(b2 +% (c2 ^ (d2 | ^e2)) +% w9 +% 0x50A28BE6, 13) +% a2; d2 := rol(d2, 10); - a2 := rol(a2 +% (b2 ^ (c2 | ^d2)) +% w2 +% 0x50A28BE6, 15) +% e2; c2 := rol(c2, 10); - e2 := rol(e2 +% (a2 ^ (b2 | ^c2)) +% w11 +% 0x50A28BE6, 15) +% d2; b2 := rol(b2, 10); - d2 := rol(d2 +% (e2 ^ (a2 | ^b2)) +% w4 +% 0x50A28BE6, 5) +% c2; a2 := rol(a2, 10); - c2 := rol(c2 +% (d2 ^ (e2 | ^a2)) +% w13 +% 0x50A28BE6, 7) +% b2; e2 := rol(e2, 10); - b2 := rol(b2 +% (c2 ^ (d2 | ^e2)) +% w6 +% 0x50A28BE6, 7) +% a2; d2 := rol(d2, 10); - a2 := rol(a2 +% (b2 ^ (c2 | ^d2)) +% w15 +% 0x50A28BE6, 8) +% e2; c2 := rol(c2, 10); - e2 := rol(e2 +% (a2 ^ (b2 | ^c2)) +% w8 +% 0x50A28BE6, 11) +% d2; b2 := rol(b2, 10); - d2 := rol(d2 +% (e2 ^ (a2 | ^b2)) +% w1 +% 0x50A28BE6, 14) +% c2; a2 := rol(a2, 10); - c2 := rol(c2 +% (d2 ^ (e2 | ^a2)) +% w10 +% 0x50A28BE6, 14) +% b2; e2 := rol(e2, 10); - b2 := rol(b2 +% (c2 ^ (d2 | ^e2)) +% w3 +% 0x50A28BE6, 12) +% a2; d2 := rol(d2, 10); - a2 := rol(a2 +% (b2 ^ (c2 | ^d2)) +% w12 +% 0x50A28BE6, 6) +% e2; c2 := rol(c2, 10); + // ---- Right line round 1: f5, K = 0x50A28BE6 + a2 := rol(a2 +% (b2 ^ (c2 | ^d2)) +% w5 +% 0x50A28BE6, 8) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% (a2 ^ (b2 | ^c2)) +% w14 +% 0x50A28BE6, 9) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% (e2 ^ (a2 | ^b2)) +% w7 +% 0x50A28BE6, 9) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% (d2 ^ (e2 | ^a2)) +% w0 +% 0x50A28BE6, 11) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% (c2 ^ (d2 | ^e2)) +% w9 +% 0x50A28BE6, 13) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% (b2 ^ (c2 | ^d2)) +% w2 +% 0x50A28BE6, 15) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% (a2 ^ (b2 | ^c2)) +% w11 +% 0x50A28BE6, 15) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% (e2 ^ (a2 | ^b2)) +% w4 +% 0x50A28BE6, 5) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% (d2 ^ (e2 | ^a2)) +% w13 +% 0x50A28BE6, 7) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% (c2 ^ (d2 | ^e2)) +% w6 +% 0x50A28BE6, 7) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% (b2 ^ (c2 | ^d2)) +% w15 +% 0x50A28BE6, 8) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% (a2 ^ (b2 | ^c2)) +% w8 +% 0x50A28BE6, 11) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% (e2 ^ (a2 | ^b2)) +% w1 +% 0x50A28BE6, 14) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% (d2 ^ (e2 | ^a2)) +% w10 +% 0x50A28BE6, 14) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% (c2 ^ (d2 | ^e2)) +% w3 +% 0x50A28BE6, 12) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% (b2 ^ (c2 | ^d2)) +% w12 +% 0x50A28BE6, 6) +% e2; c2 := rol(c2, 10); - // ---- Right line round 2: f4, K = 0x5C4DD124 - e2 := rol(e2 +% ((a2 & c2) | (b2 & ^c2)) +% w6 +% 0x5C4DD124, 9) +% d2; b2 := rol(b2, 10); - d2 := rol(d2 +% ((e2 & b2) | (a2 & ^b2)) +% w11 +% 0x5C4DD124, 13) +% c2; a2 := rol(a2, 10); - c2 := rol(c2 +% ((d2 & a2) | (e2 & ^a2)) +% w3 +% 0x5C4DD124, 15) +% b2; e2 := rol(e2, 10); - b2 := rol(b2 +% ((c2 & e2) | (d2 & ^e2)) +% w7 +% 0x5C4DD124, 7) +% a2; d2 := rol(d2, 10); - a2 := rol(a2 +% ((b2 & d2) | (c2 & ^d2)) +% w0 +% 0x5C4DD124, 12) +% e2; c2 := rol(c2, 10); - e2 := rol(e2 +% ((a2 & c2) | (b2 & ^c2)) +% w13 +% 0x5C4DD124, 8) +% d2; b2 := rol(b2, 10); - d2 := rol(d2 +% ((e2 & b2) | (a2 & ^b2)) +% w5 +% 0x5C4DD124, 9) +% c2; a2 := rol(a2, 10); - c2 := rol(c2 +% ((d2 & a2) | (e2 & ^a2)) +% w10 +% 0x5C4DD124, 11) +% b2; e2 := rol(e2, 10); - b2 := rol(b2 +% ((c2 & e2) | (d2 & ^e2)) +% w14 +% 0x5C4DD124, 7) +% a2; d2 := rol(d2, 10); - a2 := rol(a2 +% ((b2 & d2) | (c2 & ^d2)) +% w15 +% 0x5C4DD124, 7) +% e2; c2 := rol(c2, 10); - e2 := rol(e2 +% ((a2 & c2) | (b2 & ^c2)) +% w8 +% 0x5C4DD124, 12) +% d2; b2 := rol(b2, 10); - d2 := rol(d2 +% ((e2 & b2) | (a2 & ^b2)) +% w12 +% 0x5C4DD124, 7) +% c2; a2 := rol(a2, 10); - c2 := rol(c2 +% ((d2 & a2) | (e2 & ^a2)) +% w4 +% 0x5C4DD124, 6) +% b2; e2 := rol(e2, 10); - b2 := rol(b2 +% ((c2 & e2) | (d2 & ^e2)) +% w9 +% 0x5C4DD124, 15) +% a2; d2 := rol(d2, 10); - a2 := rol(a2 +% ((b2 & d2) | (c2 & ^d2)) +% w1 +% 0x5C4DD124, 13) +% e2; c2 := rol(c2, 10); - e2 := rol(e2 +% ((a2 & c2) | (b2 & ^c2)) +% w2 +% 0x5C4DD124, 11) +% d2; b2 := rol(b2, 10); + // ---- Right line round 2: f4, K = 0x5C4DD124 + e2 := rol(e2 +% ((a2 & c2) | (b2 & ^c2)) +% w6 +% 0x5C4DD124, 9) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 & b2) | (a2 & ^b2)) +% w11 +% 0x5C4DD124, 13) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 & a2) | (e2 & ^a2)) +% w3 +% 0x5C4DD124, 15) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 & e2) | (d2 & ^e2)) +% w7 +% 0x5C4DD124, 7) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 & d2) | (c2 & ^d2)) +% w0 +% 0x5C4DD124, 12) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 & c2) | (b2 & ^c2)) +% w13 +% 0x5C4DD124, 8) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 & b2) | (a2 & ^b2)) +% w5 +% 0x5C4DD124, 9) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 & a2) | (e2 & ^a2)) +% w10 +% 0x5C4DD124, 11) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 & e2) | (d2 & ^e2)) +% w14 +% 0x5C4DD124, 7) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 & d2) | (c2 & ^d2)) +% w15 +% 0x5C4DD124, 7) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 & c2) | (b2 & ^c2)) +% w8 +% 0x5C4DD124, 12) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 & b2) | (a2 & ^b2)) +% w12 +% 0x5C4DD124, 7) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 & a2) | (e2 & ^a2)) +% w4 +% 0x5C4DD124, 6) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 & e2) | (d2 & ^e2)) +% w9 +% 0x5C4DD124, 15) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 & d2) | (c2 & ^d2)) +% w1 +% 0x5C4DD124, 13) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 & c2) | (b2 & ^c2)) +% w2 +% 0x5C4DD124, 11) +% d2; b2 := rol(b2, 10); - // ---- Right line round 3: f3, K = 0x6D703EF3 - d2 := rol(d2 +% ((e2 | ^a2) ^ b2) +% w15 +% 0x6D703EF3, 9) +% c2; a2 := rol(a2, 10); - c2 := rol(c2 +% ((d2 | ^e2) ^ a2) +% w5 +% 0x6D703EF3, 7) +% b2; e2 := rol(e2, 10); - b2 := rol(b2 +% ((c2 | ^d2) ^ e2) +% w1 +% 0x6D703EF3, 15) +% a2; d2 := rol(d2, 10); - a2 := rol(a2 +% ((b2 | ^c2) ^ d2) +% w3 +% 0x6D703EF3, 11) +% e2; c2 := rol(c2, 10); - e2 := rol(e2 +% ((a2 | ^b2) ^ c2) +% w7 +% 0x6D703EF3, 8) +% d2; b2 := rol(b2, 10); - d2 := rol(d2 +% ((e2 | ^a2) ^ b2) +% w14 +% 0x6D703EF3, 6) +% c2; a2 := rol(a2, 10); - c2 := rol(c2 +% ((d2 | ^e2) ^ a2) +% w6 +% 0x6D703EF3, 6) +% b2; e2 := rol(e2, 10); - b2 := rol(b2 +% ((c2 | ^d2) ^ e2) +% w9 +% 0x6D703EF3, 14) +% a2; d2 := rol(d2, 10); - a2 := rol(a2 +% ((b2 | ^c2) ^ d2) +% w11 +% 0x6D703EF3, 12) +% e2; c2 := rol(c2, 10); - e2 := rol(e2 +% ((a2 | ^b2) ^ c2) +% w8 +% 0x6D703EF3, 13) +% d2; b2 := rol(b2, 10); - d2 := rol(d2 +% ((e2 | ^a2) ^ b2) +% w12 +% 0x6D703EF3, 5) +% c2; a2 := rol(a2, 10); - c2 := rol(c2 +% ((d2 | ^e2) ^ a2) +% w2 +% 0x6D703EF3, 14) +% b2; e2 := rol(e2, 10); - b2 := rol(b2 +% ((c2 | ^d2) ^ e2) +% w10 +% 0x6D703EF3, 13) +% a2; d2 := rol(d2, 10); - a2 := rol(a2 +% ((b2 | ^c2) ^ d2) +% w0 +% 0x6D703EF3, 13) +% e2; c2 := rol(c2, 10); - e2 := rol(e2 +% ((a2 | ^b2) ^ c2) +% w4 +% 0x6D703EF3, 7) +% d2; b2 := rol(b2, 10); - d2 := rol(d2 +% ((e2 | ^a2) ^ b2) +% w13 +% 0x6D703EF3, 5) +% c2; a2 := rol(a2, 10); + // ---- Right line round 3: f3, K = 0x6D703EF3 + d2 := rol(d2 +% ((e2 | ^a2) ^ b2) +% w15 +% 0x6D703EF3, 9) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 | ^e2) ^ a2) +% w5 +% 0x6D703EF3, 7) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 | ^d2) ^ e2) +% w1 +% 0x6D703EF3, 15) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 | ^c2) ^ d2) +% w3 +% 0x6D703EF3, 11) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 | ^b2) ^ c2) +% w7 +% 0x6D703EF3, 8) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 | ^a2) ^ b2) +% w14 +% 0x6D703EF3, 6) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 | ^e2) ^ a2) +% w6 +% 0x6D703EF3, 6) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 | ^d2) ^ e2) +% w9 +% 0x6D703EF3, 14) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 | ^c2) ^ d2) +% w11 +% 0x6D703EF3, 12) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 | ^b2) ^ c2) +% w8 +% 0x6D703EF3, 13) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 | ^a2) ^ b2) +% w12 +% 0x6D703EF3, 5) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 | ^e2) ^ a2) +% w2 +% 0x6D703EF3, 14) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 | ^d2) ^ e2) +% w10 +% 0x6D703EF3, 13) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 | ^c2) ^ d2) +% w0 +% 0x6D703EF3, 13) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 | ^b2) ^ c2) +% w4 +% 0x6D703EF3, 7) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 | ^a2) ^ b2) +% w13 +% 0x6D703EF3, 5) +% c2; a2 := rol(a2, 10); - // ---- Right line round 4: f2, K = 0x7A6D76E9 - c2 := rol(c2 +% ((d2 & e2) | (^d2 & a2)) +% w8 +% 0x7A6D76E9, 15) +% b2; e2 := rol(e2, 10); - b2 := rol(b2 +% ((c2 & d2) | (^c2 & e2)) +% w6 +% 0x7A6D76E9, 5) +% a2; d2 := rol(d2, 10); - a2 := rol(a2 +% ((b2 & c2) | (^b2 & d2)) +% w4 +% 0x7A6D76E9, 8) +% e2; c2 := rol(c2, 10); - e2 := rol(e2 +% ((a2 & b2) | (^a2 & c2)) +% w1 +% 0x7A6D76E9, 11) +% d2; b2 := rol(b2, 10); - d2 := rol(d2 +% ((e2 & a2) | (^e2 & b2)) +% w3 +% 0x7A6D76E9, 14) +% c2; a2 := rol(a2, 10); - c2 := rol(c2 +% ((d2 & e2) | (^d2 & a2)) +% w11 +% 0x7A6D76E9, 14) +% b2; e2 := rol(e2, 10); - b2 := rol(b2 +% ((c2 & d2) | (^c2 & e2)) +% w15 +% 0x7A6D76E9, 6) +% a2; d2 := rol(d2, 10); - a2 := rol(a2 +% ((b2 & c2) | (^b2 & d2)) +% w0 +% 0x7A6D76E9, 14) +% e2; c2 := rol(c2, 10); - e2 := rol(e2 +% ((a2 & b2) | (^a2 & c2)) +% w5 +% 0x7A6D76E9, 6) +% d2; b2 := rol(b2, 10); - d2 := rol(d2 +% ((e2 & a2) | (^e2 & b2)) +% w12 +% 0x7A6D76E9, 9) +% c2; a2 := rol(a2, 10); - c2 := rol(c2 +% ((d2 & e2) | (^d2 & a2)) +% w2 +% 0x7A6D76E9, 12) +% b2; e2 := rol(e2, 10); - b2 := rol(b2 +% ((c2 & d2) | (^c2 & e2)) +% w13 +% 0x7A6D76E9, 9) +% a2; d2 := rol(d2, 10); - a2 := rol(a2 +% ((b2 & c2) | (^b2 & d2)) +% w9 +% 0x7A6D76E9, 12) +% e2; c2 := rol(c2, 10); - e2 := rol(e2 +% ((a2 & b2) | (^a2 & c2)) +% w7 +% 0x7A6D76E9, 5) +% d2; b2 := rol(b2, 10); - d2 := rol(d2 +% ((e2 & a2) | (^e2 & b2)) +% w10 +% 0x7A6D76E9, 15) +% c2; a2 := rol(a2, 10); - c2 := rol(c2 +% ((d2 & e2) | (^d2 & a2)) +% w14 +% 0x7A6D76E9, 8) +% b2; e2 := rol(e2, 10); + // ---- Right line round 4: f2, K = 0x7A6D76E9 + c2 := rol(c2 +% ((d2 & e2) | (^d2 & a2)) +% w8 +% 0x7A6D76E9, 15) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 & d2) | (^c2 & e2)) +% w6 +% 0x7A6D76E9, 5) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 & c2) | (^b2 & d2)) +% w4 +% 0x7A6D76E9, 8) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 & b2) | (^a2 & c2)) +% w1 +% 0x7A6D76E9, 11) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 & a2) | (^e2 & b2)) +% w3 +% 0x7A6D76E9, 14) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 & e2) | (^d2 & a2)) +% w11 +% 0x7A6D76E9, 14) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 & d2) | (^c2 & e2)) +% w15 +% 0x7A6D76E9, 6) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 & c2) | (^b2 & d2)) +% w0 +% 0x7A6D76E9, 14) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 & b2) | (^a2 & c2)) +% w5 +% 0x7A6D76E9, 6) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 & a2) | (^e2 & b2)) +% w12 +% 0x7A6D76E9, 9) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 & e2) | (^d2 & a2)) +% w2 +% 0x7A6D76E9, 12) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% ((c2 & d2) | (^c2 & e2)) +% w13 +% 0x7A6D76E9, 9) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% ((b2 & c2) | (^b2 & d2)) +% w9 +% 0x7A6D76E9, 12) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% ((a2 & b2) | (^a2 & c2)) +% w7 +% 0x7A6D76E9, 5) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% ((e2 & a2) | (^e2 & b2)) +% w10 +% 0x7A6D76E9, 15) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% ((d2 & e2) | (^d2 & a2)) +% w14 +% 0x7A6D76E9, 8) +% b2; e2 := rol(e2, 10); - // ---- Right line round 5: f1, K = 0 - b2 := rol(b2 +% (c2 ^ d2 ^ e2) +% w12, 8) +% a2; d2 := rol(d2, 10); - a2 := rol(a2 +% (b2 ^ c2 ^ d2) +% w15, 5) +% e2; c2 := rol(c2, 10); - e2 := rol(e2 +% (a2 ^ b2 ^ c2) +% w10, 12) +% d2; b2 := rol(b2, 10); - d2 := rol(d2 +% (e2 ^ a2 ^ b2) +% w4, 9) +% c2; a2 := rol(a2, 10); - c2 := rol(c2 +% (d2 ^ e2 ^ a2) +% w1, 12) +% b2; e2 := rol(e2, 10); - b2 := rol(b2 +% (c2 ^ d2 ^ e2) +% w5, 5) +% a2; d2 := rol(d2, 10); - a2 := rol(a2 +% (b2 ^ c2 ^ d2) +% w8, 14) +% e2; c2 := rol(c2, 10); - e2 := rol(e2 +% (a2 ^ b2 ^ c2) +% w7, 6) +% d2; b2 := rol(b2, 10); - d2 := rol(d2 +% (e2 ^ a2 ^ b2) +% w6, 8) +% c2; a2 := rol(a2, 10); - c2 := rol(c2 +% (d2 ^ e2 ^ a2) +% w2, 13) +% b2; e2 := rol(e2, 10); - b2 := rol(b2 +% (c2 ^ d2 ^ e2) +% w13, 6) +% a2; d2 := rol(d2, 10); - a2 := rol(a2 +% (b2 ^ c2 ^ d2) +% w14, 5) +% e2; c2 := rol(c2, 10); - e2 := rol(e2 +% (a2 ^ b2 ^ c2) +% w0, 15) +% d2; b2 := rol(b2, 10); - d2 := rol(d2 +% (e2 ^ a2 ^ b2) +% w3, 13) +% c2; a2 := rol(a2, 10); - c2 := rol(c2 +% (d2 ^ e2 ^ a2) +% w9, 11) +% b2; e2 := rol(e2, 10); - b2 := rol(b2 +% (c2 ^ d2 ^ e2) +% w11, 11) +% a2; d2 := rol(d2, 10); + // ---- Right line round 5: f1, K = 0 + b2 := rol(b2 +% (c2 ^ d2 ^ e2) +% w12, 8) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% (b2 ^ c2 ^ d2) +% w15, 5) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% (a2 ^ b2 ^ c2) +% w10, 12) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% (e2 ^ a2 ^ b2) +% w4, 9) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% (d2 ^ e2 ^ a2) +% w1, 12) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% (c2 ^ d2 ^ e2) +% w5, 5) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% (b2 ^ c2 ^ d2) +% w8, 14) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% (a2 ^ b2 ^ c2) +% w7, 6) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% (e2 ^ a2 ^ b2) +% w6, 8) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% (d2 ^ e2 ^ a2) +% w2, 13) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% (c2 ^ d2 ^ e2) +% w13, 6) +% a2; d2 := rol(d2, 10); + a2 := rol(a2 +% (b2 ^ c2 ^ d2) +% w14, 5) +% e2; c2 := rol(c2, 10); + e2 := rol(e2 +% (a2 ^ b2 ^ c2) +% w0, 15) +% d2; b2 := rol(b2, 10); + d2 := rol(d2 +% (e2 ^ a2 ^ b2) +% w3, 13) +% c2; a2 := rol(a2, 10); + c2 := rol(c2 +% (d2 ^ e2 ^ a2) +% w9, 11) +% b2; e2 := rol(e2, 10); + b2 := rol(b2 +% (c2 ^ d2 ^ e2) +% w11, 11) +% a2; d2 := rol(d2, 10); + }; // Combine the two lines back into the chaining state. let t : Nat32 = s[0]; @@ -311,6 +314,7 @@ module { // 2) Fast path: process any number of full 64-byte blocks directly, // decoding 16 little-endian words inline into msg per block. + // prettier-ignore while (i + 64 <= n) { msg[0] := data[i].toNat16().toNat32() | (data[i+1].toNat16().toNat32() << 8) | (data[i+2].toNat16().toNat32() << 16) | (data[i+3].toNat16().toNat32() << 24); msg[1] := data[i+4].toNat16().toNat32() | (data[i+5].toNat16().toNat32() << 8) | (data[i+6].toNat16().toNat32() << 16) | (data[i+7].toNat16().toNat32() << 24); @@ -372,7 +376,7 @@ module { while (k < 5) { let v = s[k]; let o = k * 4; - out[o] := (v & 0xff).toNat16().toNat8(); + out[o] := (v & 0xff).toNat16().toNat8(); out[o + 1] := ((v >> 8) & 0xff).toNat16().toNat8(); out[o + 2] := ((v >> 16) & 0xff).toNat16().toNat8(); out[o + 3] := ((v >> 24) & 0xff).toNat16().toNat8(); From ada43988a3e0874c8916f1428ee27c18bd39a445 Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Thu, 23 Apr 2026 14:24:05 +0200 Subject: [PATCH 05/17] Run formatter on everything --- test/bitcoin/p2trKeyPathSigHash.test.mo | 16 ++++++++++++---- test/bitcoin/p2trScriptPathSigHash.test.mo | 10 ++++++++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/test/bitcoin/p2trKeyPathSigHash.test.mo b/test/bitcoin/p2trKeyPathSigHash.test.mo index 4229402..339d8dc 100644 --- a/test/bitcoin/p2trKeyPathSigHash.test.mo +++ b/test/bitcoin/p2trKeyPathSigHash.test.mo @@ -38,10 +38,14 @@ test( ); let hash0 = txLocktime0.createTaprootKeySpendSignatureHash( - testCase.amounts(), testCase.ownScript(), 0, + testCase.amounts(), + testCase.ownScript(), + 0, ); let hash42 = txLocktime42.createTaprootKeySpendSignatureHash( - testCase.amounts(), testCase.ownScript(), 0, + testCase.amounts(), + testCase.ownScript(), + 0, ); expect.blob(Blob.fromArray(hash0)).notEqual(Blob.fromArray(hash42)); @@ -62,10 +66,14 @@ test( ); let hash2 = txVersion2.createTaprootKeySpendSignatureHash( - testCase.amounts(), testCase.ownScript(), 0, + testCase.amounts(), + testCase.ownScript(), + 0, ); let hash1 = txVersion1.createTaprootKeySpendSignatureHash( - testCase.amounts(), testCase.ownScript(), 0, + testCase.amounts(), + testCase.ownScript(), + 0, ); expect.blob(Blob.fromArray(hash2)).notEqual(Blob.fromArray(hash1)); diff --git a/test/bitcoin/p2trScriptPathSigHash.test.mo b/test/bitcoin/p2trScriptPathSigHash.test.mo index c565413..0115d45 100644 --- a/test/bitcoin/p2trScriptPathSigHash.test.mo +++ b/test/bitcoin/p2trScriptPathSigHash.test.mo @@ -40,10 +40,16 @@ test( let leafHash = P2tr.leafHash(testCase.leafScript()); let hash0 = txLocktime0.createTaprootScriptSpendSignatureHash( - testCase.amounts(), testCase.ownScript(), 0, leafHash, + testCase.amounts(), + testCase.ownScript(), + 0, + leafHash, ); let hash42 = txLocktime42.createTaprootScriptSpendSignatureHash( - testCase.amounts(), testCase.ownScript(), 0, leafHash, + testCase.amounts(), + testCase.ownScript(), + 0, + leafHash, ); expect.blob(Blob.fromArray(hash0)).notEqual(Blob.fromArray(hash42)); From 693fdec8aa3678f22793c1baa984cb286e690f23 Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Thu, 23 Apr 2026 14:25:15 +0200 Subject: [PATCH 06/17] Update CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff96738..370aaa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Optimize `Ripemd160`. + ## [0.2.0] - 2026-04-22 ### Changed From b709b7329e42043c9eb318f1371f6bef50e2b97e Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Thu, 23 Apr 2026 14:33:37 +0200 Subject: [PATCH 07/17] Make use of explodeNat32() --- src/Ripemd160.mo | 47 +++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/src/Ripemd160.mo b/src/Ripemd160.mo index ca3e0a0..aaafc77 100644 --- a/src/Ripemd160.mo +++ b/src/Ripemd160.mo @@ -3,6 +3,7 @@ import Nat16 "mo:core/Nat16"; import Nat32 "mo:core/Nat32"; import Nat64 "mo:core/Nat64"; import VarArray "mo:core/VarArray"; +import Prim "mo:prim"; module { // Hash the given array and return finalized result. @@ -344,12 +345,6 @@ module { }; }; - // Convert a 64-bit value's low byte to Nat8 without going through Nat - // (avoids arbitrary-precision allocation in the padding path). - private func lowByte64(v : Nat64) : Nat8 { - (v & 0xff).toNat32().toNat16().toNat8(); - }; - public func sum() : [Nat8] { // Total message length in bits, captured before padding is appended. let bitlen : Nat64 = ((n_blocks << 6) +% Nat64.fromNat(Nat16.toNat(i_msg))) << 3; @@ -360,29 +355,29 @@ module { while (i_msg != 56) { writeByte(0); }; - writeByte(lowByte64(bitlen)); - writeByte(lowByte64(bitlen >> 8)); - writeByte(lowByte64(bitlen >> 16)); - writeByte(lowByte64(bitlen >> 24)); - writeByte(lowByte64(bitlen >> 32)); - writeByte(lowByte64(bitlen >> 40)); - writeByte(lowByte64(bitlen >> 48)); - writeByte(lowByte64(bitlen >> 56)); + writeByte(Nat8.fromIntWrap(Nat64.toNat(bitlen))); + writeByte(Nat8.fromIntWrap(Nat64.toNat(bitlen >> 8))); + writeByte(Nat8.fromIntWrap(Nat64.toNat(bitlen >> 16))); + writeByte(Nat8.fromIntWrap(Nat64.toNat(bitlen >> 24))); + writeByte(Nat8.fromIntWrap(Nat64.toNat(bitlen >> 32))); + writeByte(Nat8.fromIntWrap(Nat64.toNat(bitlen >> 40))); + writeByte(Nat8.fromIntWrap(Nat64.toNat(bitlen >> 48))); + writeByte(Nat8.fromIntWrap(Nat64.toNat(bitlen >> 56))); // The 8th length byte fills the block, triggering transform(). // Serialize the 5 chaining words as 20 little-endian bytes. - let out : [var Nat8] = VarArray.repeat(0, 20); - var k = 0; - while (k < 5) { - let v = s[k]; - let o = k * 4; - out[o] := (v & 0xff).toNat16().toNat8(); - out[o + 1] := ((v >> 8) & 0xff).toNat16().toNat8(); - out[o + 2] := ((v >> 16) & 0xff).toNat16().toNat8(); - out[o + 3] := ((v >> 24) & 0xff).toNat16().toNat8(); - k += 1; - }; - out.toArray(); + let (b3, b2, b1, b0) = Prim.explodeNat32(s[0]); + let (b7, b6, b5, b4) = Prim.explodeNat32(s[1]); + let (b11, b10, b9, b8) = Prim.explodeNat32(s[2]); + let (b15, b14, b13, b12) = Prim.explodeNat32(s[3]); + let (b19, b18, b17, b16) = Prim.explodeNat32(s[4]); + [ + b0, b1, b2, b3, + b4, b5, b6, b7, + b8, b9, b10, b11, + b12, b13, b14, b15, + b16, b17, b18, b19, + ]; }; }; }; From e0050c29fb721a5d07df2bc5885f1420562b3a34 Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Thu, 23 Apr 2026 14:35:39 +0200 Subject: [PATCH 08/17] Run formatter --- src/Ripemd160.mo | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Ripemd160.mo b/src/Ripemd160.mo index aaafc77..37950bb 100644 --- a/src/Ripemd160.mo +++ b/src/Ripemd160.mo @@ -366,11 +366,13 @@ module { // The 8th length byte fills the block, triggering transform(). // Serialize the 5 chaining words as 20 little-endian bytes. - let (b3, b2, b1, b0) = Prim.explodeNat32(s[0]); - let (b7, b6, b5, b4) = Prim.explodeNat32(s[1]); - let (b11, b10, b9, b8) = Prim.explodeNat32(s[2]); + let (b3, b2, b1, b0) = Prim.explodeNat32(s[0]); + let (b7, b6, b5, b4) = Prim.explodeNat32(s[1]); + let (b11, b10, b9, b8) = Prim.explodeNat32(s[2]); let (b15, b14, b13, b12) = Prim.explodeNat32(s[3]); let (b19, b18, b17, b16) = Prim.explodeNat32(s[4]); + + // prettier-ignore [ b0, b1, b2, b3, b4, b5, b6, b7, From ffdb3ba86f45f8e1ee5b7790d0c45d498afcc720 Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Thu, 23 Apr 2026 14:38:12 +0200 Subject: [PATCH 09/17] Fixes by CodeRabbit --- CHANGELOG.md | 2 ++ src/Ripemd160.mo | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 370aaa6..a9d4942 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + - Optimize `Ripemd160`. ## [0.2.0] - 2026-04-22 diff --git a/src/Ripemd160.mo b/src/Ripemd160.mo index 37950bb..cc967d6 100644 --- a/src/Ripemd160.mo +++ b/src/Ripemd160.mo @@ -345,6 +345,14 @@ module { }; }; + // Finalize the digest and return the 20-byte RIPEMD-160 hash. + // + // NOTE: sum() is consuming. It appends padding via writeByte(), which + // advances the internal state (s, i_msg, n_blocks) and processes the + // final block. Calling sum() a second time without an intervening + // reset() will hash additional padding bytes on top of the already- + // padded state and produce a different (incorrect) result. Call + // reset() before reusing the Digest for another message. public func sum() : [Nat8] { // Total message length in bits, captured before padding is appended. let bitlen : Nat64 = ((n_blocks << 6) +% Nat64.fromNat(Nat16.toNat(i_msg))) << 3; From ab54ad323a92ad203917fe06ab325cb130997cdf Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Thu, 23 Apr 2026 14:49:09 +0200 Subject: [PATCH 10/17] Update CHANGELOG with PR number --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9d4942..9aa1146 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- Optimize `Ripemd160`. +- Optimize `Ripemd160` (#20). ## [0.2.0] - 2026-04-22 From 40a6f5c869dc7e3c142657c5e5e137099d042e7a Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Tue, 28 Apr 2026 11:15:33 +0200 Subject: [PATCH 11/17] Protect Ripemd160 Digest from accidental writes after sum() --- src/Ripemd160.mo | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Ripemd160.mo b/src/Ripemd160.mo index cc967d6..5b474a9 100644 --- a/src/Ripemd160.mo +++ b/src/Ripemd160.mo @@ -32,6 +32,9 @@ module { // Number of complete 64-byte blocks already absorbed. private var n_blocks : Nat64 = 0; + // Flag to close Digest after call to sum() + private var closed = false; + private func initialize() { s[0] := 0x67452301; s[1] := 0xEFCDAB89; @@ -47,6 +50,7 @@ module { public func reset() { initialize(); + closed := false; }; private func rol(x : Nat32, r : Nat32) : Nat32 { @@ -303,6 +307,9 @@ module { }; public func write(data : [Nat8]) { + // Don't allow writes if Digest is closed, i.e. after sum() + assert (not closed); + let n = data.size(); if (n == 0) return; var i = 0; @@ -354,6 +361,12 @@ module { // padded state and produce a different (incorrect) result. Call // reset() before reusing the Digest for another message. public func sum() : [Nat8] { + // Prevent sum() from being called twice. + assert (not closed); + + // Close Digest for futher writes. + closed := true; + // Total message length in bits, captured before padding is appended. let bitlen : Nat64 = ((n_blocks << 6) +% Nat64.fromNat(Nat16.toNat(i_msg))) << 3; From 95912c1d11e7100d6725707150ee5c58a670ae66 Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Tue, 28 Apr 2026 11:21:39 +0200 Subject: [PATCH 12/17] Protect Hmac class from accidental writes after sum() --- src/Hmac.mo | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Hmac.mo b/src/Hmac.mo index 2f2f1b8..89e759e 100644 --- a/src/Hmac.mo +++ b/src/Hmac.mo @@ -48,6 +48,7 @@ module { let outerDigest : Digest = digestFactory.create(); let innerPad : Nat8 = 0x36; let outerPad : Nat8 = 0x5c; + var closed = false; do { let blockSize = digestFactory.blockSize; @@ -99,10 +100,13 @@ module { }; public func writeArray(data : [Nat8]) { + assert (not closed); innerDigest.writeArray(data); }; public func sum() : Blob { + assert (not closed); + closed := true; let innerHash = innerDigest.sum().toArray(); outerDigest.writeArray(innerHash); outerDigest.sum(); From 3234636d7aa0dc4c7f659c3804c3e4afe16b8d99 Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Tue, 28 Apr 2026 13:29:01 +0200 Subject: [PATCH 13/17] Formatting --- src/Ripemd160.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ripemd160.mo b/src/Ripemd160.mo index 5b474a9..076f14d 100644 --- a/src/Ripemd160.mo +++ b/src/Ripemd160.mo @@ -363,7 +363,7 @@ module { public func sum() : [Nat8] { // Prevent sum() from being called twice. assert (not closed); - + // Close Digest for futher writes. closed := true; From fbaf19fcefa55ca4588121f8edeba31e0f2e1797 Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Tue, 28 Apr 2026 13:50:15 +0200 Subject: [PATCH 14/17] Update the comment in Ripemd160 about sum() locking the Digest --- src/Ripemd160.mo | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Ripemd160.mo b/src/Ripemd160.mo index 076f14d..4300474 100644 --- a/src/Ripemd160.mo +++ b/src/Ripemd160.mo @@ -354,12 +354,9 @@ module { // Finalize the digest and return the 20-byte RIPEMD-160 hash. // - // NOTE: sum() is consuming. It appends padding via writeByte(), which - // advances the internal state (s, i_msg, n_blocks) and processes the - // final block. Calling sum() a second time without an intervening - // reset() will hash additional padding bytes on top of the already- - // padded state and produce a different (incorrect) result. Call - // reset() before reusing the Digest for another message. + // NOTE: sum() is consuming and locks the Digest. + // Calling sum() a second time or calling one of the write..() functions after sum() will trap. + // You have to call reset() before you can re-use a Digest for another message. public func sum() : [Nat8] { // Prevent sum() from being called twice. assert (not closed); From a2fc7bb56b759ce0a01d2e6b9d8a85ad0b1d2ae9 Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Tue, 28 Apr 2026 13:56:40 +0200 Subject: [PATCH 15/17] Add comment in Hmac to explain it locks after calling sum() --- src/Hmac.mo | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Hmac.mo b/src/Hmac.mo index 89e759e..a9c9c2f 100644 --- a/src/Hmac.mo +++ b/src/Hmac.mo @@ -15,8 +15,18 @@ module { create : () -> Digest; }; + // HMAC instance. + // + // NOTE: An Hmac is one-shot. Calling `sum()` finalizes and consumes the + // instance: `closed` is set, and any subsequent call to `sum()` or + // `writeArray()` will trap. To compute another HMAC, construct a new Hmac. public type Hmac = { + // Append `data` to the message being authenticated. Traps if the Hmac + // has already been finalized via `sum()`. writeArray : ([Nat8]) -> (); + // Finalize the HMAC and return the tag. Consumes the Hmac: the instance + // becomes closed, and any further call to `sum()` or `writeArray()` + // will trap. Callers must create a new Hmac for another computation. sum : () -> Blob; }; From 2b1a96b0a371655180278b6902f111f2ac3c660a Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Tue, 28 Apr 2026 14:06:06 +0200 Subject: [PATCH 16/17] Update CHANGELOG about the new guards --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9aa1146..1f90b55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Optimize `Ripemd160` (#20). +### Fixed + +- `Ripemd160` and `Hmac` Digests now guard against accidentally writing more data after calling `sum()`. + ## [0.2.0] - 2026-04-22 ### Changed From d8853cda9b27cb5fd209068e7a6bba814a9a4de3 Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Tue, 28 Apr 2026 14:12:40 +0200 Subject: [PATCH 17/17] Add Ripemd160 test with full block plus tail input --- test/ripemd160.test.mo | 69 ++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/test/ripemd160.test.mo b/test/ripemd160.test.mo index d8e58f7..ac02fea 100644 --- a/test/ripemd160.test.mo +++ b/test/ripemd160.test.mo @@ -1,9 +1,12 @@ import Nat "mo:core/Nat"; // @testmode wasi -import VarArray "mo:core/VarArray"; +import Array "mo:core/Array"; import Blob "mo:core/Blob"; +import Nat8 "mo:core/Nat8"; import Text "mo:core/Text"; +import VarArray "mo:core/VarArray"; + import Ripemd160 "../src/Ripemd160"; import { test } "mo:test"; @@ -115,28 +118,48 @@ test( digest.write(Blob.toArray(Text.encodeUtf8("vwxyz"))); assert ( - [ - 247, - 28, - 39, - 16, - 156, - 105, - 44, - 27, - 86, - 187, - 220, - 235, - 91, - 157, - 40, - 101, - 179, - 112, - 141, - 188, - ] == digest.sum() + // prettier-ignore + digest.sum() == [ + 247, 28, 39, 16, 156, 105, 44, 27, 86, 187, 220, 235, 91, 157, 40, 101, + 179, 112, 141, 188 + ] ); }, ); + +test( + "single write spanning full block + tail", + func() { + // 96 bytes = one full 64-byte block + 32 tail bytes, exercising both the + // full-block fast path and the tail path inside Ripemd160.write(). + let input : [Nat8] = Array.tabulate(96, func i { Nat8.fromIntWrap(i * 19 + 7) }); + let expected : [Nat8] = [ + 0xc3, + 0xfd, + 0x14, + 0xbf, + 0x82, + 0xc7, + 0x10, + 0x5e, + 0xd2, + 0x86, + 0x0c, + 0xa8, + 0xa3, + 0xa2, + 0xad, + 0x54, + 0x8b, + 0x74, + 0x71, + 0x5a, + ]; + + assert (Ripemd160.hash(input) == expected); + + let digest : Ripemd160.Digest = Ripemd160.Digest(); + digest.write(input); + assert (digest.sum() == expected); + }, +);