poly1305Mac function
Computes the 16-byte Poly1305 MAC of message under the 32-byte
one-time key oneTimeKey32, per RFC 8439 sec. 2.5.
Implementation
Uint8List poly1305Mac(Uint8List oneTimeKey32, Uint8List message) {
if (oneTimeKey32.length != 32) {
throw ArgumentError('one-time key must be 32 bytes');
}
// r = le_bytes_to_num(key[0..15]) & clamp ; s = le_bytes_to_num(key[16..31])
var r = BigInt.zero;
for (var i = 15; i >= 0; i--) {
r = (r << 8) | BigInt.from(oneTimeKey32[i]);
}
r = r & _clampMask;
var s = BigInt.zero;
for (var i = 31; i >= 16; i--) {
s = (s << 8) | BigInt.from(oneTimeKey32[i]);
}
var acc = BigInt.zero;
var offset = 0;
while (offset < message.length) {
final chunk = message.length - offset;
final n = chunk < 16 ? chunk : 16;
// Read block as little-endian and append a 1 byte at the top.
var block = BigInt.zero;
for (var i = n - 1; i >= 0; i--) {
block = (block << 8) | BigInt.from(message[offset + i]);
}
block = block | (BigInt.one << (n * 8));
acc = (acc + block);
acc = (r * acc) % _p1305;
offset += n;
}
acc = (acc + s) & ((BigInt.one << 128) - BigInt.one);
final tag = Uint8List(16);
var t = acc;
for (var i = 0; i < 16; i++) {
tag[i] = (t & BigInt.from(0xff)).toInt();
t = t >> 8;
}
return tag;
}