decryptSync method
List<int>
decryptSync(
- SecretBox secretBox, {
- required SecretKeyData secretKeyData,
- List<
int> aad = const <int>[],
Implementation
List<int> decryptSync(
SecretBox secretBox, {
required SecretKeyData secretKeyData,
List<int> aad = const <int>[],
}) {
final actualSecretKeyLength = secretKeyData.bytes.length;
final expectedSecretKeyLength = secretKeyLength;
if (actualSecretKeyLength != expectedSecretKeyLength) {
throw ArgumentError.value(
secretKeyData,
'secretKeyData',
'Expected $expectedSecretKeyLength bytes, got $actualSecretKeyLength bytes',
);
}
final nonce = secretBox.nonce;
final expandedKey = aesExpandKeyForEncrypting(secretKeyData);
final h = Uint32List(4);
aesEncryptBlock(h, 0, h, 0, expandedKey);
h[0] = _uint32ChangeEndian(h[0]);
h[1] = _uint32ChangeEndian(h[1]);
h[2] = _uint32ChangeEndian(h[2]);
h[3] = _uint32ChangeEndian(h[3]);
// Calculate initial nonce
var stateBytes = _nonceToBlock(h: h, nonce: nonce);
var state = Uint32List.view(stateBytes.buffer);
// Calculate MAC
final cipherText = secretBox.cipherText;
final mac = secretBox.mac;
final calculatedMac = const DartGcm()._calculateMacSync(
cipherText,
aad: aad,
expandedKey: expandedKey,
h: h,
precounterBlock: state,
);
// Check MAC is correct
if (calculatedMac != mac) {
throw SecretBoxAuthenticationError();
}
// Increment nonce
bytesIncrementBigEndian(stateBytes, 1);
// Allocate output bytes
final blockCount = (cipherText.length + 31) ~/ 16;
final keyStream = Uint32List(blockCount * 4);
// For each key stream block
for (var i = 0; i < keyStream.length; i += 4) {
// Encrypt state.
aesEncryptBlock(keyStream, i, state, 0, expandedKey);
// Increment state.
bytesIncrementBigEndian(stateBytes, 1);
}
// clearText = keyStream ^ ciphertext`
final clearText = Uint8List.view(
keyStream.buffer,
keyStream.offsetInBytes,
cipherText.length,
);
for (var i = 0; i < cipherText.length; i++) {
clearText[i] ^= cipherText[i];
}
return clearText;
}