Fix/Update #1
							
								
								
									
										28
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| { | ||||
|     // Use IntelliSense to learn about possible attributes. | ||||
|     // Hover to view descriptions of existing attributes. | ||||
|     // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||||
|     "version": "0.2.0", | ||||
|     "configurations": [ | ||||
|         { | ||||
|             "name": "native_crypto", | ||||
|             "cwd": "packages/native_crypto/example", | ||||
|             "request": "launch", | ||||
|             "type": "dart" | ||||
|         }, | ||||
|         { | ||||
|             "name": "native_crypto (profile mode)", | ||||
|             "cwd": "packages/native_crypto/example", | ||||
|             "request": "launch", | ||||
|             "type": "dart", | ||||
|             "flutterMode": "profile" | ||||
|         }, | ||||
|         { | ||||
|             "name": "native_crypto (release mode)", | ||||
|             "cwd": "packages/native_crypto/example", | ||||
|             "request": "launch", | ||||
|             "type": "dart", | ||||
|             "flutterMode": "release" | ||||
|         }, | ||||
|     ] | ||||
| } | ||||
| @ -3,7 +3,7 @@ | ||||
| // ----- | ||||
| // File: cipher_page.dart | ||||
| // Created Date: 28/12/2021 13:33:15 | ||||
| // Last Modified: 28/12/2021 15:20:43 | ||||
| // Last Modified: 25/05/2022 10:49:30 | ||||
| // ----- | ||||
| // Copyright (c) 2021 | ||||
| 
 | ||||
| @ -85,8 +85,8 @@ class CipherPage extends ConsumerWidget { | ||||
|         var bytesToString = plainText.toStr(); | ||||
|         decryptionStatus | ||||
|             .print('String successfully decrypted:\n\n$bytesToString'); | ||||
|       } on DecryptionException catch (e) { | ||||
|         decryptionStatus.print(e.message); | ||||
|       } on NativeCryptoException catch (e) { | ||||
|         decryptionStatus.print(e.message ?? 'Decryption failed!'); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| // ----- | ||||
| // File: native_crypto.dart | ||||
| // Created Date: 16/12/2021 16:28:00 | ||||
| // Last Modified: 23/05/2022 23:09:10 | ||||
| // Last Modified: 25/05/2022 10:48:20 | ||||
| // ----- | ||||
| // Copyright (c) 2021 | ||||
| 
 | ||||
| @ -13,6 +13,8 @@ | ||||
| /// Author: Hugo Pointcheval | ||||
| library native_crypto; | ||||
| 
 | ||||
| export 'package:native_crypto_platform_interface/src/utils/exception.dart'; | ||||
| 
 | ||||
| export 'src/builders/builders.dart'; | ||||
| export 'src/ciphers/ciphers.dart'; | ||||
| export 'src/core/core.dart'; | ||||
|  | ||||
| @ -3,14 +3,14 @@ | ||||
| // ----- | ||||
| // File: aes_builder.dart | ||||
| // Created Date: 28/12/2021 12:03:11 | ||||
| // Last Modified: 23/05/2022 23:05:19 | ||||
| // Last Modified: 25/05/2022 10:47:11 | ||||
| // ----- | ||||
| // Copyright (c) 2021 | ||||
| 
 | ||||
| import 'package:native_crypto/src/ciphers/aes/aes.dart'; | ||||
| import 'package:native_crypto/src/core/exceptions.dart'; | ||||
| import 'package:native_crypto/src/interfaces/builder.dart'; | ||||
| import 'package:native_crypto/src/keys/secret_key.dart'; | ||||
| import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart'; | ||||
| 
 | ||||
| class AESBuilder implements Builder<AES> { | ||||
|   SecretKey? _sk; | ||||
| @ -36,7 +36,10 @@ class AESBuilder implements Builder<AES> { | ||||
|   Future<AES> build() async { | ||||
|     if (_sk == null) { | ||||
|       if (_fsk == null) { | ||||
|         throw CipherInitException('You must specify or generate a secret key.'); | ||||
|         throw const CipherInitException( | ||||
|           message: 'You must specify or generate a secret key.', | ||||
|           code: 'missing_key', | ||||
|         ); | ||||
|       } else { | ||||
|         _sk = await _fsk; | ||||
|       } | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| // ----- | ||||
| // File: aes.dart | ||||
| // Created Date: 16/12/2021 16:28:00 | ||||
| // Last Modified: 24/05/2022 23:29:42 | ||||
| // Last Modified: 25/05/2022 10:44:25 | ||||
| // ----- | ||||
| // Copyright (c) 2022 | ||||
| 
 | ||||
| @ -14,11 +14,11 @@ import 'package:native_crypto/src/ciphers/aes/aes_mode.dart'; | ||||
| import 'package:native_crypto/src/ciphers/aes/aes_padding.dart'; | ||||
| import 'package:native_crypto/src/core/cipher_text.dart'; | ||||
| import 'package:native_crypto/src/core/cipher_text_list.dart'; | ||||
| import 'package:native_crypto/src/core/exceptions.dart'; | ||||
| import 'package:native_crypto/src/interfaces/cipher.dart'; | ||||
| import 'package:native_crypto/src/keys/secret_key.dart'; | ||||
| import 'package:native_crypto/src/platform.dart'; | ||||
| import 'package:native_crypto/src/utils/cipher_algorithm.dart'; | ||||
| import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart'; | ||||
| 
 | ||||
| export 'package:native_crypto/src/ciphers/aes/aes_key_size.dart'; | ||||
| export 'package:native_crypto/src/ciphers/aes/aes_mode.dart'; | ||||
| @ -34,16 +34,21 @@ class AES implements Cipher { | ||||
| 
 | ||||
|   AES(this.key, this.mode, {this.padding = AESPadding.none}) { | ||||
|     if (!AESKeySize.supportedSizes.contains(key.bytes.length * 8)) { | ||||
|       throw CipherInitException('Invalid key length!'); | ||||
|       throw const CipherInitException( | ||||
|         message: 'Invalid key length!', | ||||
|         code: 'invalid_key_length', | ||||
|       ); | ||||
|     } | ||||
| 
 | ||||
|     final Map<AESMode, List<AESPadding>> _supported = { | ||||
|       AESMode.gcm: [AESPadding.none], | ||||
|       AESMode.cbc: [AESPadding.pkcs5], | ||||
|     }; | ||||
| 
 | ||||
|     if (!_supported[mode]!.contains(padding)) { | ||||
|       throw CipherInitException('Invalid padding!'); | ||||
|       throw const CipherInitException( | ||||
|         message: 'Invalid padding!', | ||||
|         code: 'invalid_padding', | ||||
|       ); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  | ||||
| @ -3,9 +3,9 @@ | ||||
| // ----- | ||||
| // File: aes_mode.dart | ||||
| // Created Date: 23/05/2022 22:09:16 | ||||
| // Last Modified: 24/05/2022 23:17:01 | ||||
| // Last Modified: 25/05/2022 09:23:54 | ||||
| // ----- | ||||
| // Copyright (c) 2022 | ||||
| 
 | ||||
| /// Defines the AES modes of operation. | ||||
| enum AESMode { gcm, cbc } | ||||
| enum AESMode { gcm } | ||||
|  | ||||
| @ -3,9 +3,9 @@ | ||||
| // ----- | ||||
| // File: aes_padding.dart | ||||
| // Created Date: 23/05/2022 22:10:17 | ||||
| // Last Modified: 24/05/2022 23:17:25 | ||||
| // Last Modified: 25/05/2022 09:23:49 | ||||
| // ----- | ||||
| // Copyright (c) 2022 | ||||
| 
 | ||||
| /// Represents different paddings. | ||||
| enum AESPadding { none, pkcs5 } | ||||
| enum AESPadding { none } | ||||
|  | ||||
| @ -3,10 +3,9 @@ | ||||
| // ----- | ||||
| // File: core.dart | ||||
| // Created Date: 23/05/2022 23:05:26 | ||||
| // Last Modified: 23/05/2022 23:05:30 | ||||
| // Last Modified: 25/05/2022 10:44:32 | ||||
| // ----- | ||||
| // Copyright (c) 2022 | ||||
| 
 | ||||
| export 'cipher_text.dart'; | ||||
| export 'cipher_text_list.dart'; | ||||
| export 'exceptions.dart'; | ||||
|  | ||||
| @ -1,41 +0,0 @@ | ||||
| // Author: Hugo Pointcheval | ||||
| // Email: git@pcl.ovh | ||||
| // ----- | ||||
| // File: exceptions.dart | ||||
| // Created Date: 16/12/2021 16:28:00 | ||||
| // Last Modified: 23/05/2022 22:30:27 | ||||
| // ----- | ||||
| // Copyright (c) 2021 | ||||
| 
 | ||||
| class NativeCryptoException implements Exception { | ||||
|   final String message; | ||||
|   const NativeCryptoException(this.message); | ||||
| } | ||||
| 
 | ||||
| class UtilsException extends NativeCryptoException { | ||||
|   UtilsException(super.message); | ||||
| } | ||||
| 
 | ||||
| class KeyException extends NativeCryptoException { | ||||
|   KeyException(super.message); | ||||
| } | ||||
| 
 | ||||
| class KeyDerivationException extends NativeCryptoException { | ||||
|   KeyDerivationException(super.message); | ||||
| } | ||||
| 
 | ||||
| class CipherInitException extends NativeCryptoException { | ||||
|   CipherInitException(super.message); | ||||
| } | ||||
| 
 | ||||
| class EncryptionException extends NativeCryptoException { | ||||
|   EncryptionException(super.message); | ||||
| } | ||||
| 
 | ||||
| class DecryptionException extends NativeCryptoException { | ||||
|   DecryptionException(super.message); | ||||
| } | ||||
| 
 | ||||
| class NotImplementedException extends NativeCryptoException { | ||||
|   NotImplementedException(super.message); | ||||
| } | ||||
| @ -3,18 +3,18 @@ | ||||
| // ----- | ||||
| // File: pbkdf2.dart | ||||
| // Created Date: 17/12/2021 14:50:42 | ||||
| // Last Modified: 23/05/2022 23:07:19 | ||||
| // Last Modified: 25/05/2022 10:45:00 | ||||
| // ----- | ||||
| // Copyright (c) 2021 | ||||
| 
 | ||||
| import 'dart:typed_data'; | ||||
| 
 | ||||
| import 'package:native_crypto/src/core/exceptions.dart'; | ||||
| import 'package:native_crypto/src/interfaces/keyderivation.dart'; | ||||
| import 'package:native_crypto/src/keys/secret_key.dart'; | ||||
| import 'package:native_crypto/src/platform.dart'; | ||||
| import 'package:native_crypto/src/utils/hash_algorithm.dart'; | ||||
| import 'package:native_crypto/src/utils/kdf_algorithm.dart'; | ||||
| import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart'; | ||||
| 
 | ||||
| class Pbkdf2 extends KeyDerivation { | ||||
|   final int _keyBytesCount; | ||||
| @ -35,7 +35,10 @@ class Pbkdf2 extends KeyDerivation { | ||||
|   @override | ||||
|   Future<SecretKey> derive({String? password, String? salt}) async { | ||||
|     if (password == null || salt == null) { | ||||
|       throw KeyDerivationException("Password or Salt can't be null!"); | ||||
|       throw const KeyDerivationException( | ||||
|         message: "Password or Salt can't be null!", | ||||
|         code: 'invalid_password_or_salt', | ||||
|       ); | ||||
|     } | ||||
| 
 | ||||
|     final Uint8List derivation = (await platform.pbkdf2( | ||||
|  | ||||
| @ -3,16 +3,15 @@ | ||||
| // ----- | ||||
| // File: secret_key.dart | ||||
| // Created Date: 28/12/2021 13:36:54 | ||||
| // Last Modified: 23/05/2022 23:07:28 | ||||
| // Last Modified: 25/05/2022 10:45:55 | ||||
| // ----- | ||||
| // Copyright (c) 2021 | ||||
| 
 | ||||
| import 'dart:typed_data'; | ||||
| 
 | ||||
| import 'package:flutter/services.dart'; | ||||
| import 'package:native_crypto/src/core/exceptions.dart'; | ||||
| import 'package:native_crypto/src/interfaces/key.dart'; | ||||
| import 'package:native_crypto/src/platform.dart'; | ||||
| import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart'; | ||||
| 
 | ||||
| /// A class representing a secret key. | ||||
| /// A secret key is a key that is not accessible by anyone else. | ||||
| @ -29,8 +28,12 @@ class SecretKey extends Key { | ||||
|           (await platform.generateSecretKey(bitsCount)) ?? Uint8List(0); | ||||
| 
 | ||||
|       return SecretKey(_key); | ||||
|     } on PlatformException catch (e) { | ||||
|       throw KeyException(e.toString()); | ||||
|     } catch (e, s) { | ||||
|       throw KeyException( | ||||
|         message: 'Failed to generate a secret key!', | ||||
|         code: 'failed_to_generate_secret_key', | ||||
|         stackTrace: s, | ||||
|       ); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| // ----- | ||||
| // File: platform.dart | ||||
| // Created Date: 27/12/2021 22:03:58 | ||||
| // Last Modified: 27/12/2021 22:04:30 | ||||
| // Last Modified: 25/05/2022 10:09:18 | ||||
| // ----- | ||||
| // Copyright (c) 2021 | ||||
| 
 | ||||
|  | ||||
| @ -11,74 +11,45 @@ class AES : Cipher { | ||||
|     override val algorithm: CipherAlgorithm | ||||
|         get() = CipherAlgorithm.aes | ||||
| 
 | ||||
|     var forEncryption: Boolean = true | ||||
|     var cipherInstance: javax.crypto.Cipher? = null; | ||||
|     var secretKey: SecretKeySpec? = null; | ||||
| 
 | ||||
| /*    override fun encrypt(data: ByteArray, key: ByteArray): ByteArray { | ||||
|         val sk: SecretKey = SecretKeySpec(key, "AES") | ||||
|         val cipher = javax.crypto.Cipher.getInstance("AES/GCM/NoPadding") | ||||
|         cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, sk) | ||||
|         // javax.crypto representation = [CIPHERTEXT(n-16) || TAG(16)] | ||||
|         val bytes = cipher.doFinal(data) | ||||
|         val iv = cipher.iv.copyOf()                                                 // 12 bytes nonce | ||||
|         // native.crypto representation = [NONCE(12) || CIPHERTEXT(n-28) || TAG(16)] | ||||
|         return iv.plus(bytes) | ||||
|     fun lazyLoadCipher() { | ||||
|         if (cipherInstance == null) { | ||||
|             cipherInstance = javax.crypto.Cipher.getInstance("AES/GCM/NoPadding") | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun decrypt(data: ByteArray, key: ByteArray): ByteArray { | ||||
|         val sk: SecretKey = SecretKeySpec(key, "AES") | ||||
|         // native.crypto representation = [NONCE(12) || CIPHERTEXT(n-16) || TAG(16)] | ||||
|         val iv: ByteArray = data.take(12).toByteArray() | ||||
|         // javax.crypto representation = [CIPHERTEXT(n-28) || TAG(16)] | ||||
|         val payload: ByteArray = data.drop(12).toByteArray() | ||||
|         val spec = GCMParameterSpec(16 * 8, iv) | ||||
|         val cipher = javax.crypto.Cipher.getInstance("AES/GCM/NoPadding") | ||||
|         cipher.init(javax.crypto.Cipher.DECRYPT_MODE, sk, spec) | ||||
|         return cipher.doFinal(payload) | ||||
|     }*/ | ||||
| 
 | ||||
|     // native.crypto cipherText representation = [NONCE(12) || CIPHERTEXT(n-28) || TAG(16)] | ||||
|     // javax.crypto cipherText representation = [NONCE(12)] + [CIPHERTEXT(n-16) || TAG(16)] | ||||
|     override fun encrypt(data: ByteArray, key: ByteArray): ByteArray { | ||||
|         val list : List<ByteArray> = encryptAsList(data, key) | ||||
|         return list.first().plus(list.last()) | ||||
|     } | ||||
| 
 | ||||
|     // native.crypto cipherText representation = [NONCE(12)] + [CIPHERTEXT(n-16) || TAG(16)] | ||||
|     // javax.crypto cipherText representation = [NONCE(12)] + [CIPHERTEXT(n-16) || TAG(16)] | ||||
|     override fun encryptAsList(data: ByteArray, key: ByteArray): List<ByteArray> { | ||||
|         val sk = SecretKeySpec(key, "AES") | ||||
|         if (cipherInstance == null || !forEncryption || secretKey != sk) { | ||||
|             secretKey = sk | ||||
|             forEncryption = true | ||||
|             // native.crypto representation = [IV(16) || CIPHERTEXT(n-16)] | ||||
|             // javax.crypto representation = [CIPHERTEXT(n-16)] | ||||
|             cipherInstance = javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding") | ||||
|         lazyLoadCipher() | ||||
|         cipherInstance!!.init(javax.crypto.Cipher.ENCRYPT_MODE, sk) | ||||
|         } | ||||
|         // javax.crypto representation = [CIPHERTEXT(n-16)] | ||||
|         val bytes: ByteArray = cipherInstance!!.doFinal(data) | ||||
|         val iv: ByteArray = cipherInstance!!.iv | ||||
|         // native.crypto representation = [IV(16) || CIPHERTEXT(n-16)] | ||||
|         return listOf(iv, bytes) | ||||
|     } | ||||
| 
 | ||||
|     override fun decrypt(data: ByteArray, key: ByteArray): ByteArray { | ||||
|         // javax.crypto representation = [CIPHERTEXT(n-16)] | ||||
|         val iv: ByteArray = data.take(16).toByteArray() | ||||
|         val payload: ByteArray = data.drop(16).toByteArray() | ||||
|         val iv: ByteArray = data.take(12).toByteArray() | ||||
|         val payload: ByteArray = data.drop(12).toByteArray() | ||||
|         return decryptAsList(listOf(iv, payload), key) | ||||
|     } | ||||
| 
 | ||||
|     override fun decryptAsList(data: List<ByteArray>, key: ByteArray): ByteArray { | ||||
|         if (cipherInstance == null) { | ||||
|             // native.crypto representation = [IV(16) || CIPHERTEXT(n-16)] | ||||
|             // javax.crypto representation = [CIPHERTEXT(n-16)] | ||||
|             cipherInstance = javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding") | ||||
|         } | ||||
|         val sk = SecretKeySpec(key, "AES") | ||||
|         val iv: ByteArray = data.first() | ||||
|         val ivSpec = IvParameterSpec(iv) | ||||
|         cipherInstance!!.init(javax.crypto.Cipher.DECRYPT_MODE, sk, ivSpec) | ||||
|         forEncryption = false | ||||
|         val payload: ByteArray = data.last() | ||||
|         val iv: ByteArray = data.first() | ||||
|         val gcmSpec = GCMParameterSpec(16 * 8, iv) | ||||
|         lazyLoadCipher() | ||||
|         cipherInstance!!.init(javax.crypto.Cipher.DECRYPT_MODE, sk, gcmSpec) | ||||
|         return cipherInstance!!.doFinal(payload) | ||||
|     } | ||||
| } | ||||
| @ -3,7 +3,7 @@ | ||||
| // ----- | ||||
| // File: native_crypto_method_channel.dart | ||||
| // Created Date: 25/12/2021 16:58:04 | ||||
| // Last Modified: 24/05/2022 22:59:32 | ||||
| // Last Modified: 25/05/2022 10:40:29 | ||||
| // ----- | ||||
| // Copyright (c) 2021 | ||||
| 
 | ||||
| @ -11,7 +11,7 @@ import 'dart:typed_data'; | ||||
| 
 | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:flutter/services.dart'; | ||||
| import 'package:native_crypto_platform_interface/src/platform_interface/native_crypto_platform.dart'; | ||||
| import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart'; | ||||
| 
 | ||||
| /// An implementation of [NativeCryptoPlatform] that uses method channels. | ||||
| class MethodChannelNativeCrypto extends NativeCryptoPlatform { | ||||
| @ -20,24 +20,32 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | ||||
|   MethodChannel channel = const MethodChannel('plugins.hugop.cl/native_crypto'); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Uint8List?> digest(Uint8List data, String algorithm) { | ||||
|     return channel.invokeMethod<Uint8List>( | ||||
|   Future<Uint8List?> digest(Uint8List data, String algorithm) async { | ||||
|     try { | ||||
|       return await channel.invokeMethod<Uint8List>( | ||||
|         'digest', | ||||
|         <String, dynamic>{ | ||||
|           'data': data, | ||||
|           'algorithm': algorithm, | ||||
|         }, | ||||
|       ); | ||||
|     } catch (e, s) { | ||||
|       NativeCryptoException.convertPlatformException(e, s); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<Uint8List?> generateSecretKey(int bitsCount) { | ||||
|     return channel.invokeMethod<Uint8List>( | ||||
|   Future<Uint8List?> generateSecretKey(int bitsCount) async { | ||||
|     try { | ||||
|       return await channel.invokeMethod<Uint8List>( | ||||
|         'generateSecretKey', | ||||
|         <String, dynamic>{ | ||||
|           'bitsCount': bitsCount, | ||||
|         }, | ||||
|       ); | ||||
|     } catch (e, s) { | ||||
|       NativeCryptoException.convertPlatformException(e, s); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
| @ -47,8 +55,9 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | ||||
|     int keyBytesCount, | ||||
|     int iterations, | ||||
|     String algorithm, | ||||
|   ) { | ||||
|     return channel.invokeMethod<Uint8List>( | ||||
|   ) async { | ||||
|     try { | ||||
|       return await channel.invokeMethod<Uint8List>( | ||||
|         'pbkdf2', | ||||
|         <String, dynamic>{ | ||||
|           'password': password, | ||||
| @ -58,6 +67,9 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | ||||
|           'algorithm': algorithm, | ||||
|         }, | ||||
|       ); | ||||
|     } catch (e, s) { | ||||
|       NativeCryptoException.convertPlatformException(e, s); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
| @ -65,8 +77,9 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | ||||
|     Uint8List data, | ||||
|     Uint8List key, | ||||
|     String algorithm, | ||||
|   ) { | ||||
|     return channel.invokeListMethod( | ||||
|   ) async { | ||||
|     try { | ||||
|       return await channel.invokeListMethod( | ||||
|         'encryptAsList', | ||||
|         <String, dynamic>{ | ||||
|           'data': data, | ||||
| @ -74,6 +87,9 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | ||||
|           'algorithm': algorithm, | ||||
|         }, | ||||
|       ); | ||||
|     } catch (e, s) { | ||||
|       NativeCryptoException.convertPlatformException(e, s); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
| @ -81,8 +97,9 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | ||||
|     List<Uint8List> data, | ||||
|     Uint8List key, | ||||
|     String algorithm, | ||||
|   ) { | ||||
|     return channel.invokeMethod<Uint8List>( | ||||
|   ) async { | ||||
|     try { | ||||
|       return await channel.invokeMethod<Uint8List>( | ||||
|         'decryptAsList', | ||||
|         <String, dynamic>{ | ||||
|           'data': data, | ||||
| @ -90,6 +107,9 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | ||||
|           'algorithm': algorithm, | ||||
|         }, | ||||
|       ); | ||||
|     } catch (e, s) { | ||||
|       NativeCryptoException.convertPlatformException(e, s); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
| @ -97,8 +117,9 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | ||||
|     Uint8List data, | ||||
|     Uint8List key, | ||||
|     String algorithm, | ||||
|   ) { | ||||
|     return channel.invokeMethod<Uint8List>( | ||||
|   ) async { | ||||
|     try { | ||||
|       return await channel.invokeMethod<Uint8List>( | ||||
|         'encrypt', | ||||
|         <String, dynamic>{ | ||||
|           'data': data, | ||||
| @ -106,6 +127,9 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | ||||
|           'algorithm': algorithm, | ||||
|         }, | ||||
|       ); | ||||
|     } catch (e, s) { | ||||
|       NativeCryptoException.convertPlatformException(e, s); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
| @ -113,8 +137,9 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | ||||
|     Uint8List data, | ||||
|     Uint8List key, | ||||
|     String algorithm, | ||||
|   ) { | ||||
|     return channel.invokeMethod<Uint8List>( | ||||
|   ) async { | ||||
|     try { | ||||
|       return await channel.invokeMethod<Uint8List>( | ||||
|         'decrypt', | ||||
|         <String, dynamic>{ | ||||
|           'data': data, | ||||
| @ -122,5 +147,8 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | ||||
|           'algorithm': algorithm, | ||||
|         }, | ||||
|       ); | ||||
|     } catch (e, s) { | ||||
|       NativeCryptoException.convertPlatformException(e, s); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -3,28 +3,58 @@ | ||||
| // ----- | ||||
| // File: exception.dart | ||||
| // Created Date: 24/05/2022 18:54:48 | ||||
| // Last Modified: 24/05/2022 18:58:39 | ||||
| // Last Modified: 25/05/2022 10:43:29 | ||||
| // ----- | ||||
| // Copyright (c) 2022 | ||||
| 
 | ||||
| import 'dart:developer'; | ||||
| 
 | ||||
| import 'package:flutter/services.dart'; | ||||
| 
 | ||||
| class NativeCryptoException implements Exception { | ||||
|   final String message; | ||||
|   const NativeCryptoException(this.message); | ||||
|   const NativeCryptoException({ | ||||
|     this.message, | ||||
|     String? code, | ||||
|     this.stackTrace, | ||||
|     // ignore: unnecessary_this | ||||
|   }) : this.code = code ?? 'unknown'; | ||||
| 
 | ||||
|   /// The long form message of the exception. | ||||
|   final String? message; | ||||
| 
 | ||||
|   /// The optional code to accommodate the message. | ||||
|   final String code; | ||||
| 
 | ||||
|   /// The stack trace which provides information to the user about the call | ||||
|   /// sequence that triggered an exception | ||||
|   final StackTrace? stackTrace; | ||||
| 
 | ||||
|   @override | ||||
|   String toString() { | ||||
|     String output = '[NativeException/$code] $message'; | ||||
| 
 | ||||
|     if (stackTrace != null) { | ||||
|       output += '\n\n${stackTrace.toString()}'; | ||||
|     } | ||||
| 
 | ||||
|     return output; | ||||
|   } | ||||
| 
 | ||||
|   /// Catches a [PlatformException] and returns an [Exception]. | ||||
|   /// | ||||
|   /// If the [Exception] is a [PlatformException], | ||||
|   /// a [NativeCryptoException] is returned. | ||||
| Never convertPlatformException(Object exception, StackTrace stackTrace) { | ||||
|   static Never convertPlatformException( | ||||
|     Object exception, | ||||
|     StackTrace stackTrace, | ||||
|   ) { | ||||
|     log(exception.toString()); | ||||
|     if (exception is! Exception || exception is! PlatformException) { | ||||
|       Error.throwWithStackTrace(exception, stackTrace); | ||||
|     } | ||||
| 
 | ||||
|     Error.throwWithStackTrace( | ||||
|     platformExceptionToNativeCryptoException(exception, stackTrace), | ||||
|       NativeCryptoException.fromPlatformException(exception, stackTrace), | ||||
|       stackTrace, | ||||
|     ); | ||||
|   } | ||||
| @ -33,7 +63,7 @@ Never convertPlatformException(Object exception, StackTrace stackTrace) { | ||||
|   /// | ||||
|   /// A [PlatformException] can only be converted to a [NativeCryptoException] | ||||
|   /// if the `details` of the exception exist. | ||||
| NativeCryptoException platformExceptionToNativeCryptoException( | ||||
|   factory NativeCryptoException.fromPlatformException( | ||||
|     PlatformException platformException, | ||||
|     StackTrace stackTrace, | ||||
|   ) { | ||||
| @ -43,11 +73,81 @@ NativeCryptoException platformExceptionToNativeCryptoException( | ||||
|           ) | ||||
|         : null; | ||||
| 
 | ||||
|     String code = 'unknown'; | ||||
|     String message = platformException.message ?? ''; | ||||
| 
 | ||||
|     if (details != null) { | ||||
|       code = details['code'] ?? code; | ||||
|       message = details['message'] ?? message; | ||||
|     } | ||||
| 
 | ||||
|   return NativeCryptoException(message); | ||||
|     return NativeCryptoException( | ||||
|       message: message, | ||||
|       code: code, | ||||
|       stackTrace: stackTrace, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   // ignore: avoid_equals_and_hash_code_on_mutable_classes | ||||
|   bool operator ==(Object other) { | ||||
|     if (identical(this, other)) return true; | ||||
| 
 | ||||
|     return other is NativeCryptoException && | ||||
|         other.message == message && | ||||
|         other.code == code && | ||||
|         other.stackTrace == stackTrace; | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   // ignore: avoid_equals_and_hash_code_on_mutable_classes | ||||
|   int get hashCode => message.hashCode ^ code.hashCode ^ stackTrace.hashCode; | ||||
| } | ||||
| 
 | ||||
| class KeyException extends NativeCryptoException { | ||||
|   const KeyException({ | ||||
|     super.message, | ||||
|     super.code, | ||||
|     super.stackTrace, | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| class KeyDerivationException extends NativeCryptoException { | ||||
|   const KeyDerivationException({ | ||||
|     super.message, | ||||
|     super.code, | ||||
|     super.stackTrace, | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| class CipherInitException extends NativeCryptoException { | ||||
|   const CipherInitException({ | ||||
|     super.message, | ||||
|     super.code, | ||||
|     super.stackTrace, | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| class EncryptionException extends NativeCryptoException { | ||||
|   const EncryptionException({ | ||||
|     super.message, | ||||
|     super.code, | ||||
|     super.stackTrace, | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| class DecryptionException extends NativeCryptoException { | ||||
|   const DecryptionException({ | ||||
|     super.message, | ||||
|     super.code, | ||||
|     super.stackTrace, | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| class NotImplementedException extends NativeCryptoException { | ||||
|   const NotImplementedException({ | ||||
|     super.message, | ||||
|     super.code, | ||||
|     super.stackTrace, | ||||
|   }); | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user