chacha20Poly1305Decrypt function

Uint8List chacha20Poly1305Decrypt({
  1. required Uint8List key32,
  2. required Uint8List nonce12,
  3. required Uint8List ciphertextWithTag,
  4. Uint8List? aad,
})

Verifies and decrypts ciphertextWithTag (ciphertext || 16-byte tag).

Returns the plaintext, or throws FormatException('invalid tag') if the authentication tag does not match.

Implementation

Uint8List chacha20Poly1305Decrypt({
  required Uint8List key32,
  required Uint8List nonce12,
  required Uint8List ciphertextWithTag,
  Uint8List? aad,
}) {
  if (ciphertextWithTag.length < 16) {
    throw FormatException('invalid tag');
  }
  final ad = aad ?? Uint8List(0);
  final ctLen = ciphertextWithTag.length - 16;
  final ciphertext = Uint8List.sublistView(ciphertextWithTag, 0, ctLen);
  final tag = Uint8List.sublistView(ciphertextWithTag, ctLen);

  final otk = _poly1305KeyGen(key32, nonce12);
  final macData = _aeadMacData(ad, ciphertext);
  final expected = poly1305Mac(otk, macData);

  // Constant-time comparison.
  var diff = 0;
  for (var i = 0; i < 16; i++) {
    diff |= tag[i] ^ expected[i];
  }
  if (diff != 0) {
    throw FormatException('invalid tag');
  }

  return _chacha20Xor(key32, nonce12, ciphertext, 1);
}