chacha20Block function
Generates one 64-byte ChaCha20 keystream block for the given 32-byte key32,
32-bit block counter and 12-byte nonce12.
Implementation
Uint8List chacha20Block(Uint8List key32, int counter, Uint8List nonce12) {
if (key32.length != 32) {
throw ArgumentError('key must be 32 bytes');
}
if (nonce12.length != 12) {
throw ArgumentError('nonce must be 12 bytes');
}
final state = Uint32List(16);
// Constants: "expand 32-byte k"
state[0] = 0x61707865;
state[1] = 0x3320646e;
state[2] = 0x79622d32;
state[3] = 0x6b206574;
// Key
for (var i = 0; i < 8; i++) {
state[4 + i] = _le32(key32, i * 4);
}
// Counter
state[12] = counter & _mask32;
// Nonce
state[13] = _le32(nonce12, 0);
state[14] = _le32(nonce12, 4);
state[15] = _le32(nonce12, 8);
final working = Uint32List.fromList(state);
for (var i = 0; i < 10; i++) {
// Column rounds
_quarterRound(working, 0, 4, 8, 12);
_quarterRound(working, 1, 5, 9, 13);
_quarterRound(working, 2, 6, 10, 14);
_quarterRound(working, 3, 7, 11, 15);
// Diagonal rounds
_quarterRound(working, 0, 5, 10, 15);
_quarterRound(working, 1, 6, 11, 12);
_quarterRound(working, 2, 7, 8, 13);
_quarterRound(working, 3, 4, 9, 14);
}
final out = Uint8List(64);
for (var i = 0; i < 16; i++) {
final word = (working[i] + state[i]) & _mask32;
out[i * 4] = word & 0xff;
out[i * 4 + 1] = (word >> 8) & 0xff;
out[i * 4 + 2] = (word >> 16) & 0xff;
out[i * 4 + 3] = (word >> 24) & 0xff;
}
return out;
}