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 | // File: cipher_page.dart | ||||||
| // Created Date: 28/12/2021 13:33:15 | // 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 | // Copyright (c) 2021 | ||||||
| 
 | 
 | ||||||
| @ -85,8 +85,8 @@ class CipherPage extends ConsumerWidget { | |||||||
|         var bytesToString = plainText.toStr(); |         var bytesToString = plainText.toStr(); | ||||||
|         decryptionStatus |         decryptionStatus | ||||||
|             .print('String successfully decrypted:\n\n$bytesToString'); |             .print('String successfully decrypted:\n\n$bytesToString'); | ||||||
|       } on DecryptionException catch (e) { |       } on NativeCryptoException catch (e) { | ||||||
|         decryptionStatus.print(e.message); |         decryptionStatus.print(e.message ?? 'Decryption failed!'); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ | |||||||
| // ----- | // ----- | ||||||
| // File: native_crypto.dart | // File: native_crypto.dart | ||||||
| // Created Date: 16/12/2021 16:28:00 | // 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 | // Copyright (c) 2021 | ||||||
| 
 | 
 | ||||||
| @ -13,6 +13,8 @@ | |||||||
| /// Author: Hugo Pointcheval | /// Author: Hugo Pointcheval | ||||||
| library native_crypto; | library native_crypto; | ||||||
| 
 | 
 | ||||||
|  | export 'package:native_crypto_platform_interface/src/utils/exception.dart'; | ||||||
|  | 
 | ||||||
| export 'src/builders/builders.dart'; | export 'src/builders/builders.dart'; | ||||||
| export 'src/ciphers/ciphers.dart'; | export 'src/ciphers/ciphers.dart'; | ||||||
| export 'src/core/core.dart'; | export 'src/core/core.dart'; | ||||||
|  | |||||||
| @ -3,14 +3,14 @@ | |||||||
| // ----- | // ----- | ||||||
| // File: aes_builder.dart | // File: aes_builder.dart | ||||||
| // Created Date: 28/12/2021 12:03:11 | // 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 | // Copyright (c) 2021 | ||||||
| 
 | 
 | ||||||
| import 'package:native_crypto/src/ciphers/aes/aes.dart'; | 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/interfaces/builder.dart'; | ||||||
| import 'package:native_crypto/src/keys/secret_key.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> { | class AESBuilder implements Builder<AES> { | ||||||
|   SecretKey? _sk; |   SecretKey? _sk; | ||||||
| @ -36,7 +36,10 @@ class AESBuilder implements Builder<AES> { | |||||||
|   Future<AES> build() async { |   Future<AES> build() async { | ||||||
|     if (_sk == null) { |     if (_sk == null) { | ||||||
|       if (_fsk == 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 { |       } else { | ||||||
|         _sk = await _fsk; |         _sk = await _fsk; | ||||||
|       } |       } | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ | |||||||
| // ----- | // ----- | ||||||
| // File: aes.dart | // File: aes.dart | ||||||
| // Created Date: 16/12/2021 16:28:00 | // 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 | // 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/ciphers/aes/aes_padding.dart'; | ||||||
| import 'package:native_crypto/src/core/cipher_text.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/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/interfaces/cipher.dart'; | ||||||
| import 'package:native_crypto/src/keys/secret_key.dart'; | import 'package:native_crypto/src/keys/secret_key.dart'; | ||||||
| import 'package:native_crypto/src/platform.dart'; | import 'package:native_crypto/src/platform.dart'; | ||||||
| import 'package:native_crypto/src/utils/cipher_algorithm.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_key_size.dart'; | ||||||
| export 'package:native_crypto/src/ciphers/aes/aes_mode.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}) { |   AES(this.key, this.mode, {this.padding = AESPadding.none}) { | ||||||
|     if (!AESKeySize.supportedSizes.contains(key.bytes.length * 8)) { |     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 = { |     final Map<AESMode, List<AESPadding>> _supported = { | ||||||
|       AESMode.gcm: [AESPadding.none], |       AESMode.gcm: [AESPadding.none], | ||||||
|       AESMode.cbc: [AESPadding.pkcs5], |  | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     if (!_supported[mode]!.contains(padding)) { |     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 | // File: aes_mode.dart | ||||||
| // Created Date: 23/05/2022 22:09:16 | // 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 | // Copyright (c) 2022 | ||||||
| 
 | 
 | ||||||
| /// Defines the AES modes of operation. | /// Defines the AES modes of operation. | ||||||
| enum AESMode { gcm, cbc } | enum AESMode { gcm } | ||||||
|  | |||||||
| @ -3,9 +3,9 @@ | |||||||
| // ----- | // ----- | ||||||
| // File: aes_padding.dart | // File: aes_padding.dart | ||||||
| // Created Date: 23/05/2022 22:10:17 | // 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 | // Copyright (c) 2022 | ||||||
| 
 | 
 | ||||||
| /// Represents different paddings. | /// Represents different paddings. | ||||||
| enum AESPadding { none, pkcs5 } | enum AESPadding { none } | ||||||
|  | |||||||
| @ -3,10 +3,9 @@ | |||||||
| // ----- | // ----- | ||||||
| // File: core.dart | // File: core.dart | ||||||
| // Created Date: 23/05/2022 23:05:26 | // 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 | // Copyright (c) 2022 | ||||||
| 
 | 
 | ||||||
| export 'cipher_text.dart'; | export 'cipher_text.dart'; | ||||||
| export 'cipher_text_list.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 | // File: pbkdf2.dart | ||||||
| // Created Date: 17/12/2021 14:50:42 | // 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 | // Copyright (c) 2021 | ||||||
| 
 | 
 | ||||||
| import 'dart:typed_data'; | 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/interfaces/keyderivation.dart'; | ||||||
| import 'package:native_crypto/src/keys/secret_key.dart'; | import 'package:native_crypto/src/keys/secret_key.dart'; | ||||||
| import 'package:native_crypto/src/platform.dart'; | import 'package:native_crypto/src/platform.dart'; | ||||||
| import 'package:native_crypto/src/utils/hash_algorithm.dart'; | import 'package:native_crypto/src/utils/hash_algorithm.dart'; | ||||||
| import 'package:native_crypto/src/utils/kdf_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 { | class Pbkdf2 extends KeyDerivation { | ||||||
|   final int _keyBytesCount; |   final int _keyBytesCount; | ||||||
| @ -35,7 +35,10 @@ class Pbkdf2 extends KeyDerivation { | |||||||
|   @override |   @override | ||||||
|   Future<SecretKey> derive({String? password, String? salt}) async { |   Future<SecretKey> derive({String? password, String? salt}) async { | ||||||
|     if (password == null || salt == null) { |     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( |     final Uint8List derivation = (await platform.pbkdf2( | ||||||
|  | |||||||
| @ -3,16 +3,15 @@ | |||||||
| // ----- | // ----- | ||||||
| // File: secret_key.dart | // File: secret_key.dart | ||||||
| // Created Date: 28/12/2021 13:36:54 | // 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 | // Copyright (c) 2021 | ||||||
| 
 | 
 | ||||||
| import 'dart:typed_data'; | 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/interfaces/key.dart'; | ||||||
| import 'package:native_crypto/src/platform.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 class representing a secret key. | ||||||
| /// A secret key is a key that is not accessible by anyone else. | /// 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); |           (await platform.generateSecretKey(bitsCount)) ?? Uint8List(0); | ||||||
| 
 | 
 | ||||||
|       return SecretKey(_key); |       return SecretKey(_key); | ||||||
|     } on PlatformException catch (e) { |     } catch (e, s) { | ||||||
|       throw KeyException(e.toString()); |       throw KeyException( | ||||||
|  |         message: 'Failed to generate a secret key!', | ||||||
|  |         code: 'failed_to_generate_secret_key', | ||||||
|  |         stackTrace: s, | ||||||
|  |       ); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ | |||||||
| // ----- | // ----- | ||||||
| // File: platform.dart | // File: platform.dart | ||||||
| // Created Date: 27/12/2021 22:03:58 | // 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 | // Copyright (c) 2021 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -11,74 +11,45 @@ class AES : Cipher { | |||||||
|     override val algorithm: CipherAlgorithm |     override val algorithm: CipherAlgorithm | ||||||
|         get() = CipherAlgorithm.aes |         get() = CipherAlgorithm.aes | ||||||
| 
 | 
 | ||||||
|     var forEncryption: Boolean = true |  | ||||||
|     var cipherInstance: javax.crypto.Cipher? = null; |     var cipherInstance: javax.crypto.Cipher? = null; | ||||||
|     var secretKey: SecretKeySpec? = null; |  | ||||||
| 
 | 
 | ||||||
| /*    override fun encrypt(data: ByteArray, key: ByteArray): ByteArray { |     fun lazyLoadCipher() { | ||||||
|         val sk: SecretKey = SecretKeySpec(key, "AES") |         if (cipherInstance == null) { | ||||||
|         val cipher = javax.crypto.Cipher.getInstance("AES/GCM/NoPadding") |             cipherInstance = 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) |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun decrypt(data: ByteArray, key: ByteArray): ByteArray { |     // native.crypto cipherText representation = [NONCE(12) || CIPHERTEXT(n-28) || TAG(16)] | ||||||
|         val sk: SecretKey = SecretKeySpec(key, "AES") |     // javax.crypto cipherText representation = [NONCE(12)] + [CIPHERTEXT(n-16) || TAG(16)] | ||||||
|         // 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) |  | ||||||
|     }*/ |  | ||||||
| 
 |  | ||||||
|     override fun encrypt(data: ByteArray, key: ByteArray): ByteArray { |     override fun encrypt(data: ByteArray, key: ByteArray): ByteArray { | ||||||
|         val list : List<ByteArray> = encryptAsList(data, key) |         val list : List<ByteArray> = encryptAsList(data, key) | ||||||
|         return list.first().plus(list.last()) |         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> { |     override fun encryptAsList(data: ByteArray, key: ByteArray): List<ByteArray> { | ||||||
|         val sk = SecretKeySpec(key, "AES") |         val sk = SecretKeySpec(key, "AES") | ||||||
|         if (cipherInstance == null || !forEncryption || secretKey != sk) { |         lazyLoadCipher() | ||||||
|             secretKey = sk |         cipherInstance!!.init(javax.crypto.Cipher.ENCRYPT_MODE, 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") |  | ||||||
|             cipherInstance!!.init(javax.crypto.Cipher.ENCRYPT_MODE, sk) |  | ||||||
|         } |  | ||||||
|         // javax.crypto representation = [CIPHERTEXT(n-16)] |  | ||||||
|         val bytes: ByteArray = cipherInstance!!.doFinal(data) |         val bytes: ByteArray = cipherInstance!!.doFinal(data) | ||||||
|         val iv: ByteArray = cipherInstance!!.iv |         val iv: ByteArray = cipherInstance!!.iv | ||||||
|         // native.crypto representation = [IV(16) || CIPHERTEXT(n-16)] |  | ||||||
|         return listOf(iv, bytes) |         return listOf(iv, bytes) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun decrypt(data: ByteArray, key: ByteArray): ByteArray { |     override fun decrypt(data: ByteArray, key: ByteArray): ByteArray { | ||||||
|         // javax.crypto representation = [CIPHERTEXT(n-16)] |         val iv: ByteArray = data.take(12).toByteArray() | ||||||
|         val iv: ByteArray = data.take(16).toByteArray() |         val payload: ByteArray = data.drop(12).toByteArray() | ||||||
|         val payload: ByteArray = data.drop(16).toByteArray() |  | ||||||
|         return decryptAsList(listOf(iv, payload), key) |         return decryptAsList(listOf(iv, payload), key) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun decryptAsList(data: List<ByteArray>, key: ByteArray): ByteArray { |     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 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 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) |         return cipherInstance!!.doFinal(payload) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -3,7 +3,7 @@ | |||||||
| // ----- | // ----- | ||||||
| // File: native_crypto_method_channel.dart | // File: native_crypto_method_channel.dart | ||||||
| // Created Date: 25/12/2021 16:58:04 | // 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 | // Copyright (c) 2021 | ||||||
| 
 | 
 | ||||||
| @ -11,7 +11,7 @@ import 'dart:typed_data'; | |||||||
| 
 | 
 | ||||||
| import 'package:flutter/foundation.dart'; | import 'package:flutter/foundation.dart'; | ||||||
| import 'package:flutter/services.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. | /// An implementation of [NativeCryptoPlatform] that uses method channels. | ||||||
| class MethodChannelNativeCrypto extends NativeCryptoPlatform { | class MethodChannelNativeCrypto extends NativeCryptoPlatform { | ||||||
| @ -20,24 +20,32 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | |||||||
|   MethodChannel channel = const MethodChannel('plugins.hugop.cl/native_crypto'); |   MethodChannel channel = const MethodChannel('plugins.hugop.cl/native_crypto'); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   Future<Uint8List?> digest(Uint8List data, String algorithm) { |   Future<Uint8List?> digest(Uint8List data, String algorithm) async { | ||||||
|     return channel.invokeMethod<Uint8List>( |     try { | ||||||
|       'digest', |       return await channel.invokeMethod<Uint8List>( | ||||||
|       <String, dynamic>{ |         'digest', | ||||||
|         'data': data, |         <String, dynamic>{ | ||||||
|         'algorithm': algorithm, |           'data': data, | ||||||
|       }, |           'algorithm': algorithm, | ||||||
|     ); |         }, | ||||||
|  |       ); | ||||||
|  |     } catch (e, s) { | ||||||
|  |       NativeCryptoException.convertPlatformException(e, s); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   Future<Uint8List?> generateSecretKey(int bitsCount) { |   Future<Uint8List?> generateSecretKey(int bitsCount) async { | ||||||
|     return channel.invokeMethod<Uint8List>( |     try { | ||||||
|       'generateSecretKey', |       return await channel.invokeMethod<Uint8List>( | ||||||
|       <String, dynamic>{ |         'generateSecretKey', | ||||||
|         'bitsCount': bitsCount, |         <String, dynamic>{ | ||||||
|       }, |           'bitsCount': bitsCount, | ||||||
|     ); |         }, | ||||||
|  |       ); | ||||||
|  |     } catch (e, s) { | ||||||
|  |       NativeCryptoException.convertPlatformException(e, s); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
| @ -47,17 +55,21 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | |||||||
|     int keyBytesCount, |     int keyBytesCount, | ||||||
|     int iterations, |     int iterations, | ||||||
|     String algorithm, |     String algorithm, | ||||||
|   ) { |   ) async { | ||||||
|     return channel.invokeMethod<Uint8List>( |     try { | ||||||
|       'pbkdf2', |       return await channel.invokeMethod<Uint8List>( | ||||||
|       <String, dynamic>{ |         'pbkdf2', | ||||||
|         'password': password, |         <String, dynamic>{ | ||||||
|         'salt': salt, |           'password': password, | ||||||
|         'keyBytesCount': keyBytesCount, |           'salt': salt, | ||||||
|         'iterations': iterations, |           'keyBytesCount': keyBytesCount, | ||||||
|         'algorithm': algorithm, |           'iterations': iterations, | ||||||
|       }, |           'algorithm': algorithm, | ||||||
|     ); |         }, | ||||||
|  |       ); | ||||||
|  |     } catch (e, s) { | ||||||
|  |       NativeCryptoException.convertPlatformException(e, s); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
| @ -65,15 +77,19 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | |||||||
|     Uint8List data, |     Uint8List data, | ||||||
|     Uint8List key, |     Uint8List key, | ||||||
|     String algorithm, |     String algorithm, | ||||||
|   ) { |   ) async { | ||||||
|     return channel.invokeListMethod( |     try { | ||||||
|       'encryptAsList', |       return await channel.invokeListMethod( | ||||||
|       <String, dynamic>{ |         'encryptAsList', | ||||||
|         'data': data, |         <String, dynamic>{ | ||||||
|         'key': key, |           'data': data, | ||||||
|         'algorithm': algorithm, |           'key': key, | ||||||
|       }, |           'algorithm': algorithm, | ||||||
|     ); |         }, | ||||||
|  |       ); | ||||||
|  |     } catch (e, s) { | ||||||
|  |       NativeCryptoException.convertPlatformException(e, s); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
| @ -81,15 +97,19 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | |||||||
|     List<Uint8List> data, |     List<Uint8List> data, | ||||||
|     Uint8List key, |     Uint8List key, | ||||||
|     String algorithm, |     String algorithm, | ||||||
|   ) { |   ) async { | ||||||
|     return channel.invokeMethod<Uint8List>( |     try { | ||||||
|       'decryptAsList', |       return await channel.invokeMethod<Uint8List>( | ||||||
|       <String, dynamic>{ |         'decryptAsList', | ||||||
|         'data': data, |         <String, dynamic>{ | ||||||
|         'key': key, |           'data': data, | ||||||
|         'algorithm': algorithm, |           'key': key, | ||||||
|       }, |           'algorithm': algorithm, | ||||||
|     ); |         }, | ||||||
|  |       ); | ||||||
|  |     } catch (e, s) { | ||||||
|  |       NativeCryptoException.convertPlatformException(e, s); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
| @ -97,15 +117,19 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | |||||||
|     Uint8List data, |     Uint8List data, | ||||||
|     Uint8List key, |     Uint8List key, | ||||||
|     String algorithm, |     String algorithm, | ||||||
|   ) { |   ) async { | ||||||
|     return channel.invokeMethod<Uint8List>( |     try { | ||||||
|       'encrypt', |       return await channel.invokeMethod<Uint8List>( | ||||||
|       <String, dynamic>{ |         'encrypt', | ||||||
|         'data': data, |         <String, dynamic>{ | ||||||
|         'key': key, |           'data': data, | ||||||
|         'algorithm': algorithm, |           'key': key, | ||||||
|       }, |           'algorithm': algorithm, | ||||||
|     ); |         }, | ||||||
|  |       ); | ||||||
|  |     } catch (e, s) { | ||||||
|  |       NativeCryptoException.convertPlatformException(e, s); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
| @ -113,14 +137,18 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform { | |||||||
|     Uint8List data, |     Uint8List data, | ||||||
|     Uint8List key, |     Uint8List key, | ||||||
|     String algorithm, |     String algorithm, | ||||||
|   ) { |   ) async { | ||||||
|     return channel.invokeMethod<Uint8List>( |     try { | ||||||
|       'decrypt', |       return await channel.invokeMethod<Uint8List>( | ||||||
|       <String, dynamic>{ |         'decrypt', | ||||||
|         'data': data, |         <String, dynamic>{ | ||||||
|         'key': key, |           'data': data, | ||||||
|         'algorithm': algorithm, |           'key': key, | ||||||
|       }, |           'algorithm': algorithm, | ||||||
|     ); |         }, | ||||||
|  |       ); | ||||||
|  |     } catch (e, s) { | ||||||
|  |       NativeCryptoException.convertPlatformException(e, s); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -3,51 +3,151 @@ | |||||||
| // ----- | // ----- | ||||||
| // File: exception.dart | // File: exception.dart | ||||||
| // Created Date: 24/05/2022 18:54:48 | // 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 | // Copyright (c) 2022 | ||||||
| 
 | 
 | ||||||
|  | import 'dart:developer'; | ||||||
|  | 
 | ||||||
| import 'package:flutter/services.dart'; | import 'package:flutter/services.dart'; | ||||||
| 
 | 
 | ||||||
| class NativeCryptoException implements Exception { | class NativeCryptoException implements Exception { | ||||||
|   final String message; |   const NativeCryptoException({ | ||||||
|   const NativeCryptoException(this.message); |     this.message, | ||||||
| } |     String? code, | ||||||
|  |     this.stackTrace, | ||||||
|  |     // ignore: unnecessary_this | ||||||
|  |   }) : this.code = code ?? 'unknown'; | ||||||
| 
 | 
 | ||||||
| /// Catches a [PlatformException] and returns an [Exception]. |   /// The long form message of the exception. | ||||||
| /// |   final String? message; | ||||||
| /// If the [Exception] is a [PlatformException], | 
 | ||||||
| /// a [NativeCryptoException] is returned. |   /// The optional code to accommodate the message. | ||||||
| Never convertPlatformException(Object exception, StackTrace stackTrace) { |   final String code; | ||||||
|   if (exception is! Exception || exception is! PlatformException) { | 
 | ||||||
|     Error.throwWithStackTrace(exception, stackTrace); |   /// 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; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   Error.throwWithStackTrace( |   /// Catches a [PlatformException] and returns an [Exception]. | ||||||
|     platformExceptionToNativeCryptoException(exception, stackTrace), |   /// | ||||||
|     stackTrace, |   /// If the [Exception] is a [PlatformException], | ||||||
|   ); |   /// a [NativeCryptoException] is returned. | ||||||
| } |   static Never convertPlatformException( | ||||||
|  |     Object exception, | ||||||
|  |     StackTrace stackTrace, | ||||||
|  |   ) { | ||||||
|  |     log(exception.toString()); | ||||||
|  |     if (exception is! Exception || exception is! PlatformException) { | ||||||
|  |       Error.throwWithStackTrace(exception, stackTrace); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
| /// Converts a [PlatformException] into a [NativeCryptoException]. |     Error.throwWithStackTrace( | ||||||
| /// |       NativeCryptoException.fromPlatformException(exception, stackTrace), | ||||||
| /// A [PlatformException] can only be converted to a [NativeCryptoException] |       stackTrace, | ||||||
| /// if the `details` of the exception exist. |     ); | ||||||
| NativeCryptoException platformExceptionToNativeCryptoException( |  | ||||||
|   PlatformException platformException, |  | ||||||
|   StackTrace stackTrace, |  | ||||||
| ) { |  | ||||||
|   final Map<String, String>? details = platformException.details != null |  | ||||||
|       ? Map<String, String>.from( |  | ||||||
|           platformException.details as Map<String, String>, |  | ||||||
|         ) |  | ||||||
|       : null; |  | ||||||
| 
 |  | ||||||
|   String message = platformException.message ?? ''; |  | ||||||
| 
 |  | ||||||
|   if (details != null) { |  | ||||||
|     message = details['message'] ?? message; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return NativeCryptoException(message); |   /// Converts a [PlatformException] into a [NativeCryptoException]. | ||||||
|  |   /// | ||||||
|  |   /// A [PlatformException] can only be converted to a [NativeCryptoException] | ||||||
|  |   /// if the `details` of the exception exist. | ||||||
|  |   factory NativeCryptoException.fromPlatformException( | ||||||
|  |     PlatformException platformException, | ||||||
|  |     StackTrace stackTrace, | ||||||
|  |   ) { | ||||||
|  |     final Map<String, String>? details = platformException.details != null | ||||||
|  |         ? Map<String, String>.from( | ||||||
|  |             platformException.details as Map<String, String>, | ||||||
|  |           ) | ||||||
|  |         : null; | ||||||
|  | 
 | ||||||
|  |     String code = 'unknown'; | ||||||
|  |     String message = platformException.message ?? ''; | ||||||
|  | 
 | ||||||
|  |     if (details != null) { | ||||||
|  |       code = details['code'] ?? code; | ||||||
|  |       message = details['message'] ?? 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