decrypt method

  1. @override
List<int>? decrypt(
  1. List<int> nonce,
  2. List<int> sealed, {
  3. List<int>? associatedData,
  4. List<int>? dst,
})
override

Decrypts the provided sealed data using ChaCha20-Poly1305 decryption.

This method takes a nonce, sealed data (which includes the ciphertext and authentication tag), and optional associated data, and attempts to decrypt the sealed data. If the decryption is successful, the plaintext data is returned in the List<int> dst. If the decryption fails (e.g., due to an incorrect tag or nonce), null is returned.

Parameters:

  • nonce: The nonce as a List
  • sealed: The sealed data, including the ciphertext and authentication tag.
  • associatedData: Optional associated data that is not encrypted but used in the tag verification.
  • dst: An optional destination List<int> where the decrypted plaintext will be written.

Throws:

  • ArgumentException if the provided nonce length is incorrect or if the destination length is incorrect.

Returns:

  • The List<int> containing the decrypted plaintext data, or null if decryption fails.

Note: This method uses ChaCha20-Poly1305 decryption, including nonce handling, tag verification, and associated data processing. If the authentication tag is incorrect, null is returned to indicate decryption failure.

Implementation

@override
List<int>? decrypt(List<int> nonce, List<int> sealed,
    {List<int>? associatedData, List<int>? dst}) {
  if (nonce.length > 16) {
    throw const ArgumentException("ChaCha20Poly1305: incorrect nonce length");
  }

  if (sealed.length < tagLength) {
    return null;
  }

  final counter = List<int>.filled(16, 0);
  counter.setRange(counter.length - nonce.length, counter.length, nonce);

  final authKey = List<int>.filled(32, 0);
  ChaCha20.stream(_key, counter, authKey, nonceInplaceCounterLength: 4);

  final calculatedTag = List<int>.filled(tagLength, 0);
  _authenticate(calculatedTag, authKey,
      sealed.sublist(0, sealed.length - tagLength), associatedData);

  if (!BytesUtils.bytesEqual(
      calculatedTag, sealed.sublist(sealed.length - tagLength))) {
    return null;
  }

  final resultLength = sealed.length - tagLength;

  List<int> result = dst ?? List<int>.filled(resultLength, 0);
  if (result.length != resultLength) {
    throw const ArgumentException(
        "ChaCha20Poly1305: incorrect destination length");
  }

  ChaCha20.streamXOR(
      _key, counter, sealed.sublist(0, sealed.length - tagLength), result,
      nonceInplaceCounterLength: 4);

  zero(counter);
  return result;
}