diff --git a/packages/native_crypto/lib/src/ciphers/aes/aes.dart b/packages/native_crypto/lib/src/ciphers/aes/aes.dart index 49644fd..b1113fc 100644 --- a/packages/native_crypto/lib/src/ciphers/aes/aes.dart +++ b/packages/native_crypto/lib/src/ciphers/aes/aes.dart @@ -3,7 +3,7 @@ // ----- // File: aes.dart // Created Date: 16/12/2021 16:28:00 -// Last Modified: 26/05/2022 21:07:01 +// Last Modified: 27/05/2022 12:13:28 // ----- // Copyright (c) 2022 @@ -46,7 +46,6 @@ class AES implements Cipher { ); } - if (!mode.supportedPaddings.contains(padding)) { throw NativeCryptoException( message: 'Invalid padding! ' @@ -56,13 +55,25 @@ class AES implements Cipher { } } - Future _decrypt(CipherText cipherText, - {int chunkCount = 0,}) async { - final Uint8List? decrypted = await platform.decrypt( - cipherText.bytes, - _key.bytes, - algorithm.name, - ); + Future _decrypt( + CipherText cipherText, { + int chunkCount = 0, + }) async { + Uint8List? decrypted; + + try { + decrypted = await platform.decrypt( + cipherText.bytes, + _key.bytes, + algorithm.name, + ); + } catch (e, s) { + throw NativeCryptoException( + message: '$e', + code: NativeCryptoExceptionCode.platform_throws.code, + stackTrace: s, + ); + } if (decrypted.isNull) { throw NativeCryptoException( @@ -80,11 +91,21 @@ class AES implements Cipher { } Future _encrypt(Uint8List data, {int chunkCount = 0}) async { - final Uint8List? encrypted = await platform.encrypt( - data, - _key.bytes, - algorithm.name, - ); + Uint8List? encrypted; + + try { + encrypted = await platform.encrypt( + data, + _key.bytes, + algorithm.name, + ); + } catch (e, s) { + throw NativeCryptoException( + message: '$e on chunk #$chunkCount', + code: NativeCryptoExceptionCode.platform_throws.code, + stackTrace: s, + ); + } if (encrypted.isNull) { throw NativeCryptoException( @@ -97,13 +118,21 @@ class AES implements Cipher { code: NativeCryptoExceptionCode.platform_returned_empty_data.code, ); } else { - return CipherText.fromBytes( - encrypted, - ivLength: 12, - messageLength: encrypted.length - 28, - tagLength: 16, - cipherAlgorithm: CipherAlgorithm.aes, - ); + try { + return CipherText.fromBytes( + encrypted, + ivLength: 12, + messageLength: encrypted.length - 28, + tagLength: 16, + cipherAlgorithm: CipherAlgorithm.aes, + ); + } on NativeCryptoException catch (e, s) { + throw NativeCryptoException( + message: '${e.message} on chunk #$chunkCount', + code: e.code, + stackTrace: s, + ); + } } } @@ -125,6 +154,9 @@ class AES implements Cipher { @override Future encrypt(Uint8List data) async { + if (data.isEmpty) { + return CipherTextWrapper.empty(); + } CipherTextWrapper cipherTextWrapper; Uint8List dataToEncrypt; final int chunkNb = (data.length / Cipher.bytesCountPerChunk).ceil(); diff --git a/packages/native_crypto/lib/src/core/cipher_text.dart b/packages/native_crypto/lib/src/core/cipher_text.dart index e0c62e3..09cc4d6 100644 --- a/packages/native_crypto/lib/src/core/cipher_text.dart +++ b/packages/native_crypto/lib/src/core/cipher_text.dart @@ -3,7 +3,7 @@ // ----- // File: cipher_text.dart // Created Date: 16/12/2021 16:59:53 -// Last Modified: 26/05/2022 22:20:40 +// Last Modified: 27/05/2022 12:09:47 // ----- // Copyright (c) 2021 @@ -47,10 +47,12 @@ class CipherText extends ByteArray { factory CipherText.fromBytes( Uint8List bytes, { required int ivLength, - required int messageLength, required int tagLength, + int? messageLength, CipherAlgorithm? cipherAlgorithm, }) { + messageLength ??= bytes.length - ivLength - tagLength; + if (ivLength.isNegative || messageLength.isNegative || tagLength.isNegative) { diff --git a/packages/native_crypto/lib/src/core/cipher_text_wrapper.dart b/packages/native_crypto/lib/src/core/cipher_text_wrapper.dart index 285ba6a..75a9dae 100644 --- a/packages/native_crypto/lib/src/core/cipher_text_wrapper.dart +++ b/packages/native_crypto/lib/src/core/cipher_text_wrapper.dart @@ -3,7 +3,7 @@ // ----- // File: cipher_text_wrapper.dart // Created Date: 26/05/2022 14:27:32 -// Last Modified: 26/05/2022 22:11:42 +// Last Modified: 27/05/2022 13:43:29 // ----- // Copyright (c) 2022 @@ -51,7 +51,6 @@ class CipherTextWrapper { factory CipherTextWrapper.fromBytes( Uint8List bytes, { required int ivLength, - required int messageLength, required int tagLength, CipherAlgorithm? cipherAlgorithm, int? chunkSize, @@ -59,29 +58,38 @@ class CipherTextWrapper { chunkSize ??= Cipher.bytesCountPerChunk; Cipher.bytesCountPerChunk = chunkSize; - if (bytes.length <= chunkSize) { + final int messageLength = bytes.length - ivLength - tagLength; + + if (messageLength <= chunkSize) { return CipherTextWrapper.single( CipherText.fromBytes( bytes, ivLength: ivLength, - messageLength: messageLength, tagLength: tagLength, cipherAlgorithm: cipherAlgorithm, ), ); } else { final cipherTexts = []; - for (var i = 0; i < bytes.length; i += chunkSize) { - final chunk = bytes.sublist(i, i + chunkSize); - cipherTexts.add( - CipherText.fromBytes( - chunk, - ivLength: ivLength, - messageLength: messageLength, - tagLength: tagLength, - cipherAlgorithm: cipherAlgorithm, - ), - ); + for (var i = 0; i < bytes.length; i += chunkSize + ivLength + tagLength) { + final chunk = bytes.trySublist(i, i + chunkSize + ivLength + tagLength); + + try { + cipherTexts.add( + CipherText.fromBytes( + chunk, + ivLength: ivLength, + tagLength: tagLength, + cipherAlgorithm: cipherAlgorithm, + ), + ); + } on NativeCryptoException catch (e, s) { + throw NativeCryptoException( + message: '${e.message} on chunk #$i', + code: e.code, + stackTrace: s, + ); + } } return CipherTextWrapper.list(cipherTexts); } diff --git a/packages/native_crypto/lib/src/utils/extensions.dart b/packages/native_crypto/lib/src/utils/extensions.dart index 5daa30b..fc2a799 100644 --- a/packages/native_crypto/lib/src/utils/extensions.dart +++ b/packages/native_crypto/lib/src/utils/extensions.dart @@ -3,7 +3,7 @@ // ----- // File: extensions.dart // Created Date: 26/05/2022 12:12:48 -// Last Modified: 26/05/2022 22:15:33 +// Last Modified: 27/05/2022 12:26:55 // ----- // Copyright (c) 2022 @@ -87,4 +87,15 @@ extension Uint8ListX on Uint8List { /// Returns a concatenation of this with the other [Uint8List]. Uint8List plus(final Uint8List other) => [...this, ...other].toTypedList(); + + /// Returns a sublist of this from the [start] index to the [end] index. + /// If [end] is greater than the length of the list, it is set to the length + Uint8List trySublist(int start, [int? end]) { + if (isEmpty) return this; + + int ending = end ?? length; + if (ending > length) ending = length; + + return sublist(start, ending); + } }