gb method
RFC 9106 function GB(v0,..v3).
In the RFC, arguments are 64-bit integers. In our implementation, they are Uint32List indices.
Implementation
@visibleForTesting
void gb(Uint32List data, int a, int b, int c, int d) {
// ---------------------------------
// Browser-compatible implementation
// ---------------------------------
var v0Low = data[a];
var v0High = data[a + 1];
var v1Low = data[b];
var v1High = data[b + 1];
var v2Low = data[c];
var v2High = data[c + 1];
var v3Low = data[d];
var v3High = data[d + 1];
// a = (a + b + 2 * trunc(a) * trunc(b)) mod 2^(64)
{
var mLow =
(0xFFFF & v0Low) * v1Low + (0xFFFF0000 & v0Low) * (0xFFFF & v1Low);
var mHigh = mLow ~/ _bit32 + (v0Low >> 16) * (v1Low >> 16);
mHigh = (_mask32 & (mHigh << 1)) + (0x1 & (mLow >> 31));
mLow = _mask32 & (mLow << 1);
v0Low = v0Low + v1Low + mLow;
v0High = _mask32 & (v0High + v1High + v0Low ~/ _bit32 + mHigh);
v0Low = _mask32 & v0Low;
}
// d = (d XOR a) rotr 32
{
final tmpLow = v3Low ^ v0Low;
final tmpHigh = v3High ^ v0High;
v3Low = tmpHigh;
v3High = tmpLow;
}
// c = (c + d + 2 * trunc(c) * trunc(d)) mod 2^(64)
{
var mLow =
(0xFFFF & v2Low) * v3Low + (0xFFFF0000 & v2Low) * (0xFFFF & v3Low);
var mHigh = mLow ~/ _bit32 + (v2Low >> 16) * (v3Low >> 16);
mHigh = (_mask32 & (mHigh << 1)) + (0x1 & (mLow >> 31));
mLow = _mask32 & (mLow << 1);
v2Low = v2Low + v3Low + mLow;
v2High = _mask32 & (v2High + v3High + v2Low ~/ _bit32 + mHigh);
v2Low = _mask32 & v2Low;
}
// b = (b XOR c) rotr 24
{
final tmpLow = v1Low ^ v2Low;
final tmpHigh = v1High ^ v2High;
v1Low = ((0xFFFFFF & tmpHigh) << 8) | (tmpLow >>> 24);
v1High = ((0xFFFFFF & tmpLow) << 8) | (tmpHigh >>> 24);
}
// a = (a + b + 2 * trunc(a) * trunc(b)) mod 2^(64)
{
var mLow =
(0xFFFF & v0Low) * v1Low + (0xFFFF0000 & v0Low) * (0xFFFF & v1Low);
var mHigh = mLow ~/ _bit32 + (v0Low >> 16) * (v1Low >> 16);
mHigh = (_mask32 & (mHigh << 1)) + (0x1 & (mLow >> 31));
mLow = _mask32 & (mLow << 1);
v0Low = v0Low + v1Low + mLow;
v0High = _mask32 & (v0High + v1High + v0Low ~/ _bit32 + mHigh);
v0Low = _mask32 & v0Low;
}
// d = (d XOR a) rotr 16
{
final tmpLow = v3Low ^ v0Low;
final tmpHigh = v3High ^ v0High;
v3Low = ((0xFFFF & tmpHigh) << 16) | (tmpLow >>> 16);
v3High = ((0xFFFF & tmpLow) << 16) | (tmpHigh >>> 16);
}
// c = (c + d + 2 * trunc(c) * trunc(d)) mod 2^(64)
{
var mLow =
(0xFFFF & v2Low) * v3Low + (0xFFFF0000 & v2Low) * (0xFFFF & v3Low);
var mHigh = mLow ~/ _bit32 + (v2Low >> 16) * (v3Low >> 16);
mHigh = (_mask32 & (mHigh << 1)) + (0x1 & (mLow >> 31));
mLow = _mask32 & (mLow << 1);
v2Low = v2Low + v3Low + mLow;
v2High = _mask32 & (v2High + v3High + v2Low ~/ _bit32 + mHigh);
v2Low = _mask32 & v2Low;
}
// b = (b XOR c) rotr 63
{
final tmpLow = v1Low ^ v2Low;
final tmpHigh = v1High ^ v2High;
v1Low = (_mask32 & (tmpLow << 1)) | (tmpHigh >>> 31);
v1High = (tmpHigh << 1) | (tmpLow >>> 31);
}
data[a] = v0Low;
data[a + 1] = v0High;
data[b] = v1Low;
data[b + 1] = v1High;
data[c] = v2Low;
data[c + 1] = v2High;
data[d] = v3Low;
data[d + 1] = v3High;
}