decrypt method
Decrypts sealed data using the Galois/Counter Mode (GCM) with associated data (AEAD).
This method decrypts sealed data using the GCM mode, ensuring data integrity and authenticity with the associated data.
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 newList<int>
is created.
Returns:
- The decrypted data if authentication succeeds; otherwise, returns null if authentication fails.
Throws:
ArgumentException
if the provided nonce has an incorrect length, if the destination size is incorrect, or if the authentication tag verification fails.
Note: This method performs GCM decryption, verifying the authentication tag and ensuring the data's integrity and authenticity.
Implementation
@override
List<int>? decrypt(List<int> nonce, List<int> sealed,
{List<int>? associatedData, List<int>? dst}) {
if (nonce.length != nonceLength) {
throw const ArgumentException("GCM: incorrect nonce length");
}
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 const ArgumentException("GCM: incorrect destination length");
}
final ctr = CTR(_cipher, counter);
ctr.streamXOR(sealed.sublist(0, sealed.length - tagLength), result);
ctr.clean();
zero(counter);
zero(tagMask);
return result;
}