decryptWithPlugin static method
Future<List<int> >
decryptWithPlugin({
- required String name,
- required FlutterCipher cipher,
- Cipher? fallback,
- PaddingAlgorithm? paddingAlgorithm,
- required SecretBox secretBox,
- required SecretKey secretKey,
- required List<
int> aad,
Implementation
@protected
static Future<List<int>> decryptWithPlugin({
required String name,
required FlutterCipher cipher,
Cipher? fallback,
PaddingAlgorithm? paddingAlgorithm,
required SecretBox secretBox,
required SecretKey secretKey,
required List<int> aad,
}) async {
final secretKeyData = await secretKey.extractBytes();
final secretKeyUint8List = asUint8List(secretKeyData);
final nonceUint8List = asUint8List(secretBox.nonce);
final macUint8List = asUint8List(secretBox.mac.bytes);
final aadUint8List = asUint8List(aad);
if (secretKeyUint8List.length != cipher.secretKeyLength) {
throw ArgumentError.value(
secretKey,
'secretKey',
'Expected a secret key with ${cipher.secretKeyLength} bytes, got ${secretKeyUint8List.length} bytes.',
);
}
if (nonceUint8List.length != cipher.nonceLength) {
throw ArgumentError.value(
secretBox,
'secretBox',
'Expected a nonce with ${cipher.nonceLength} bytes, got ${nonceUint8List.length} bytes.',
);
}
final macAlgorithm = cipher.macAlgorithm;
if (macUint8List.length != macAlgorithm.macLength) {
throw SecretBoxAuthenticationError();
}
if (aadUint8List.isNotEmpty && !macAlgorithm.supportsAad) {
throw ArgumentError(
'AAD is not supported by $macAlgorithm, but parameter `aad` is non-empty.',
);
}
final cipherText = secretBox.cipherText;
final cipherTextSize = cipherText.length;
final lock = CryptographyChannelQueue.defaultInstance.newLock(
size: cipherTextSize,
);
await lock.lock();
late Map result;
try {
final cipherTextUint8List = asUint8List(secretBox.cipherText);
result = await invokeMethod(
'decrypt',
{
'algo': name,
'data': cipherTextUint8List,
'key': secretKeyUint8List,
'nonce': nonceUint8List,
'mac': macUint8List,
'aad': aadUint8List,
},
useQueue: false, // We do queueing ourselves
);
} on UnsupportedError {
if (fallback == null) {
rethrow;
}
return fallback.decrypt(
secretBox,
secretKey: secretKey,
aad: aad,
);
} on PlatformException catch (error) {
switch (error.code) {
case 'INCORRECT_MAC':
throw SecretBoxAuthenticationError();
case 'INCORRECT_PADDING':
throw SecretBoxPaddingError(
message: error.message,
);
default:
rethrow;
}
} finally {
lock.unlock();
}
final clearText = result['clearText'] as Uint8List;
// Sanity check
if (cipherTextSize != cipher.cipherTextLength(clearText.length)) {
throw StateError(
'${cipher.runtimeType}.decrypt sanity check failed: '
'clearText.length (${clearText.length}) != '
'cipherText.length ($cipherTextSize)',
);
}
return clearText;
}