poly1305Mac function

Uint8List poly1305Mac(
  1. Uint8List oneTimeKey32,
  2. Uint8List message
)

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;
}