SHA-256: the rotations masked again, as the integer rule asks

The unmasked rotations of the previous commit were exact, but on the VM
they left values of up to 62 bits in the sums, against the rule of the
package: every value in 32 bits on the VM as on the web. Masked again, the
unrolled rounds are as fast: PBKDF2 at 600 000 iterations takes about 1 s
on the VM.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.11
dev 2 days ago
parent a2e2bbfcd6
commit 4850b6bca8

@ -52,17 +52,22 @@ const _iv = [
/// Compresses the 16 words of [w] (big-endian words of one block, w[0..15];
/// w[16..63] are scratch) into the eight words of [state].
///
/// The left halves of the rotations are not masked: on the VM their bits
/// above 32 only reach sums that are masked before any other use, and an
/// addition carries upward only; on the web, `<<` keeps 32 bits itself. The
/// rounds are unrolled by eight, so that the working variables rotate by
/// name instead of by assignment.
/// Every value stays in 32 bits on the VM as on the web: the left half of
/// each rotation is masked, and each sum of at most five words is masked
/// before any other use. The rounds are unrolled by eight, so that the
/// working variables rotate by name instead of by assignment.
void _compress(Uint32List state, Uint32List w) {
for (var t = 16; t < 64; t++) {
final x = w[t - 15];
final y = w[t - 2];
final s0 = (x >>> 7 | x << 25) ^ (x >>> 18 | x << 14) ^ x >>> 3;
final s1 = (y >>> 17 | y << 15) ^ (y >>> 19 | y << 13) ^ y >>> 10;
final s0 =
(x >>> 7 | x << 25 & _mask32) ^
(x >>> 18 | x << 14 & _mask32) ^
x >>> 3;
final s1 =
(y >>> 17 | y << 15 & _mask32) ^
(y >>> 19 | y << 13 & _mask32) ^
y >>> 10;
w[t] = (w[t - 16] + s0 + w[t - 7] + s1) & _mask32;
}
var a = state[0];
@ -77,7 +82,9 @@ void _compress(Uint32List state, Uint32List w) {
// Round t + 0.
final t0 =
(h +
((e >>> 6 | e << 26) ^ (e >>> 11 | e << 21) ^ (e >>> 25 | e << 7)) +
((e >>> 6 | e << 26 & _mask32) ^
(e >>> 11 | e << 21 & _mask32) ^
(e >>> 25 | e << 7 & _mask32)) +
((e & f) ^ ((e ^ _mask32) & g)) +
_k[t + 0] +
w[t + 0]) &
@ -85,15 +92,17 @@ void _compress(Uint32List state, Uint32List w) {
d = (d + t0) & _mask32;
h =
(t0 +
((a >>> 2 | a << 30) ^
(a >>> 13 | a << 19) ^
(a >>> 22 | a << 10)) +
((a >>> 2 | a << 30 & _mask32) ^
(a >>> 13 | a << 19 & _mask32) ^
(a >>> 22 | a << 10 & _mask32)) +
((a & b) ^ (a & c) ^ (b & c))) &
_mask32;
// Round t + 1.
final t1 =
(g +
((d >>> 6 | d << 26) ^ (d >>> 11 | d << 21) ^ (d >>> 25 | d << 7)) +
((d >>> 6 | d << 26 & _mask32) ^
(d >>> 11 | d << 21 & _mask32) ^
(d >>> 25 | d << 7 & _mask32)) +
((d & e) ^ ((d ^ _mask32) & f)) +
_k[t + 1] +
w[t + 1]) &
@ -101,15 +110,17 @@ void _compress(Uint32List state, Uint32List w) {
c = (c + t1) & _mask32;
g =
(t1 +
((h >>> 2 | h << 30) ^
(h >>> 13 | h << 19) ^
(h >>> 22 | h << 10)) +
((h >>> 2 | h << 30 & _mask32) ^
(h >>> 13 | h << 19 & _mask32) ^
(h >>> 22 | h << 10 & _mask32)) +
((h & a) ^ (h & b) ^ (a & b))) &
_mask32;
// Round t + 2.
final t2 =
(f +
((c >>> 6 | c << 26) ^ (c >>> 11 | c << 21) ^ (c >>> 25 | c << 7)) +
((c >>> 6 | c << 26 & _mask32) ^
(c >>> 11 | c << 21 & _mask32) ^
(c >>> 25 | c << 7 & _mask32)) +
((c & d) ^ ((c ^ _mask32) & e)) +
_k[t + 2] +
w[t + 2]) &
@ -117,15 +128,17 @@ void _compress(Uint32List state, Uint32List w) {
b = (b + t2) & _mask32;
f =
(t2 +
((g >>> 2 | g << 30) ^
(g >>> 13 | g << 19) ^
(g >>> 22 | g << 10)) +
((g >>> 2 | g << 30 & _mask32) ^
(g >>> 13 | g << 19 & _mask32) ^
(g >>> 22 | g << 10 & _mask32)) +
((g & h) ^ (g & a) ^ (h & a))) &
_mask32;
// Round t + 3.
final t3 =
(e +
((b >>> 6 | b << 26) ^ (b >>> 11 | b << 21) ^ (b >>> 25 | b << 7)) +
((b >>> 6 | b << 26 & _mask32) ^
(b >>> 11 | b << 21 & _mask32) ^
(b >>> 25 | b << 7 & _mask32)) +
((b & c) ^ ((b ^ _mask32) & d)) +
_k[t + 3] +
w[t + 3]) &
@ -133,15 +146,17 @@ void _compress(Uint32List state, Uint32List w) {
a = (a + t3) & _mask32;
e =
(t3 +
((f >>> 2 | f << 30) ^
(f >>> 13 | f << 19) ^
(f >>> 22 | f << 10)) +
((f >>> 2 | f << 30 & _mask32) ^
(f >>> 13 | f << 19 & _mask32) ^
(f >>> 22 | f << 10 & _mask32)) +
((f & g) ^ (f & h) ^ (g & h))) &
_mask32;
// Round t + 4.
final t4 =
(d +
((a >>> 6 | a << 26) ^ (a >>> 11 | a << 21) ^ (a >>> 25 | a << 7)) +
((a >>> 6 | a << 26 & _mask32) ^
(a >>> 11 | a << 21 & _mask32) ^
(a >>> 25 | a << 7 & _mask32)) +
((a & b) ^ ((a ^ _mask32) & c)) +
_k[t + 4] +
w[t + 4]) &
@ -149,15 +164,17 @@ void _compress(Uint32List state, Uint32List w) {
h = (h + t4) & _mask32;
d =
(t4 +
((e >>> 2 | e << 30) ^
(e >>> 13 | e << 19) ^
(e >>> 22 | e << 10)) +
((e >>> 2 | e << 30 & _mask32) ^
(e >>> 13 | e << 19 & _mask32) ^
(e >>> 22 | e << 10 & _mask32)) +
((e & f) ^ (e & g) ^ (f & g))) &
_mask32;
// Round t + 5.
final t5 =
(c +
((h >>> 6 | h << 26) ^ (h >>> 11 | h << 21) ^ (h >>> 25 | h << 7)) +
((h >>> 6 | h << 26 & _mask32) ^
(h >>> 11 | h << 21 & _mask32) ^
(h >>> 25 | h << 7 & _mask32)) +
((h & a) ^ ((h ^ _mask32) & b)) +
_k[t + 5] +
w[t + 5]) &
@ -165,15 +182,17 @@ void _compress(Uint32List state, Uint32List w) {
g = (g + t5) & _mask32;
c =
(t5 +
((d >>> 2 | d << 30) ^
(d >>> 13 | d << 19) ^
(d >>> 22 | d << 10)) +
((d >>> 2 | d << 30 & _mask32) ^
(d >>> 13 | d << 19 & _mask32) ^
(d >>> 22 | d << 10 & _mask32)) +
((d & e) ^ (d & f) ^ (e & f))) &
_mask32;
// Round t + 6.
final t6 =
(b +
((g >>> 6 | g << 26) ^ (g >>> 11 | g << 21) ^ (g >>> 25 | g << 7)) +
((g >>> 6 | g << 26 & _mask32) ^
(g >>> 11 | g << 21 & _mask32) ^
(g >>> 25 | g << 7 & _mask32)) +
((g & h) ^ ((g ^ _mask32) & a)) +
_k[t + 6] +
w[t + 6]) &
@ -181,15 +200,17 @@ void _compress(Uint32List state, Uint32List w) {
f = (f + t6) & _mask32;
b =
(t6 +
((c >>> 2 | c << 30) ^
(c >>> 13 | c << 19) ^
(c >>> 22 | c << 10)) +
((c >>> 2 | c << 30 & _mask32) ^
(c >>> 13 | c << 19 & _mask32) ^
(c >>> 22 | c << 10 & _mask32)) +
((c & d) ^ (c & e) ^ (d & e))) &
_mask32;
// Round t + 7.
final t7 =
(a +
((f >>> 6 | f << 26) ^ (f >>> 11 | f << 21) ^ (f >>> 25 | f << 7)) +
((f >>> 6 | f << 26 & _mask32) ^
(f >>> 11 | f << 21 & _mask32) ^
(f >>> 25 | f << 7 & _mask32)) +
((f & g) ^ ((f ^ _mask32) & h)) +
_k[t + 7] +
w[t + 7]) &
@ -197,9 +218,9 @@ void _compress(Uint32List state, Uint32List w) {
e = (e + t7) & _mask32;
a =
(t7 +
((b >>> 2 | b << 30) ^
(b >>> 13 | b << 19) ^
(b >>> 22 | b << 10)) +
((b >>> 2 | b << 30 & _mask32) ^
(b >>> 13 | b << 19 & _mask32) ^
(b >>> 22 | b << 10 & _mask32)) +
((b & c) ^ (b & d) ^ (c & d))) &
_mask32;
}

Loading…
Cancel
Save

Powered by TurnKey Linux.