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.

Parameters:

  • nonce: The nonce, with a maximum length of 16 bytes.
  • 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 where the decrypted plaintext will be written.

Throws:

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

Implementation

@override
List<int>? decrypt(
  List<int> nonce,
  List<int> sealed, {
  List<int>? associatedData,
  List<int>? dst,
}) {
  if (nonce.length > 16) {
    throw ArgumentException.invalidOperationArguments(
      "decrypt",
      name: "nonce",
      reason: "Invalid nonce bytes 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;

  final List<int> result = dst ?? List<int>.filled(resultLength, 0);
  if (result.length != resultLength) {
    throw ArgumentException.invalidOperationArguments(
      "decrypt",
      name: "dst",
      reason: "Invalid destination bytes length.",
      expecteLen: resultLength,
    );
  }

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

  BinaryOps.zero(counter);
  return result;
}