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 sealed data using the Galois/Counter Mode (GCM) with associated data (AEAD).

Parameters:

  • nonce: The nonce value used during encryption, must have a length equal to the GCM nonce length (12 bytes).
  • sealed: The sealed data that includes the ciphertext and authentication tag.
  • associatedData: (Optional) Additional data that was authenticated during encryption but not encrypted.
  • dst: (Optional) The destination for the decrypted data. If not provided, a new List<int> is created.

Throws:

  • ArgumentException if the provided nonce has an incorrect length, if the destination size is incorrect, or if the authentication tag verification fails.

Implementation

@override
List<int>? decrypt(
  List<int> nonce,
  List<int> sealed, {
  List<int>? associatedData,
  List<int>? dst,
}) {
  if (nonce.length != nonceLength) {
    throw ArgumentException.invalidOperationArguments(
      "decrypt",
      name: "nonce",
      reason: "Incorrect nonce length.",
      expecteLen: nonceLength,
    );
  }

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

  final blockSize = _cipher.blockSize;

  final counter = List<int>.filled(blockSize, 0);
  counter.setAll(0, nonce);

  counter[blockSize - 1] = 1;

  final tagMask = List<int>.filled(blockSize, 0);
  _cipher.encryptBlock(counter, tagMask);

  counter[blockSize - 1] = 2;

  final calculatedTag = List<int>.filled(tagLength, 0);
  _authenticate(
    calculatedTag,
    tagMask,
    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: "Incorrect destination length.",
      expecteLen: resultLength,
    );
  }
  final ctr = CTR(_cipher, counter);
  ctr.streamXOR(sealed.sublist(0, sealed.length - tagLength), result);
  ctr.clean();

  BinaryOps.zero(counter);
  BinaryOps.zero(tagMask);
  return result;
}