Understanding the SHA256 Motoko Implementation
This is the source
code
being analyzed. The block size is 64
bytes and the number of rounds is 64
.
These are not explicitly defined but used inline.
1. Initialization
Line
19
defines the 64
round constants of size 32-bits each.
private let K : [Nat32] = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
...
];
Line
38
initialized the 8
initial hash values of 32-bits each.
private let S : [Nat32] = [
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
];
2. Processing
The processing phase is a collaboration between the functions
write
and
block
.
The block at Line
71
checks if there is already buffered data and appends incoming bytes to it
at most until it fills BLOCK_SIZE
.
let n = Nat.min(p.size(), 64 - nx);
for (i in Iter.range(0, n - 1)) {
x[nx + i] := p[i];
};
If the buffer size reaches BLOCK_SIZE
send to block
where the hash values
get updated:
if (nx == 64) {
let buf = Array.freeze<Nat8>(x);
block(buf);
nx := 0;
};
If the remaining data has enough bytes to fill a BLOCK_SIZE
, it will be
processed by block
up to its last chunk if it's not yet of size BLOCK_SIZE
.
3. Sum
The function
sum
handles padding and outputting the final hash.