feat: export new exceptions
This commit is contained in:
parent
a7affea1e1
commit
a1112b5c80
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")
|
||||
cipherInstance!!.init(javax.crypto.Cipher.ENCRYPT_MODE, sk)
|
||||
}
|
||||
// javax.crypto representation = [CIPHERTEXT(n-16)]
|
||||
lazyLoadCipher()
|
||||
cipherInstance!!.init(javax.crypto.Cipher.ENCRYPT_MODE, sk)
|
||||
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>(
|
||||
'digest',
|
||||
<String, dynamic>{
|
||||
'data': data,
|
||||
'algorithm': algorithm,
|
||||
},
|
||||
);
|
||||
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>(
|
||||
'generateSecretKey',
|
||||
<String, dynamic>{
|
||||
'bitsCount': bitsCount,
|
||||
},
|
||||
);
|
||||
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,17 +55,21 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform {
|
||||
int keyBytesCount,
|
||||
int iterations,
|
||||
String algorithm,
|
||||
) {
|
||||
return channel.invokeMethod<Uint8List>(
|
||||
'pbkdf2',
|
||||
<String, dynamic>{
|
||||
'password': password,
|
||||
'salt': salt,
|
||||
'keyBytesCount': keyBytesCount,
|
||||
'iterations': iterations,
|
||||
'algorithm': algorithm,
|
||||
},
|
||||
);
|
||||
) async {
|
||||
try {
|
||||
return await channel.invokeMethod<Uint8List>(
|
||||
'pbkdf2',
|
||||
<String, dynamic>{
|
||||
'password': password,
|
||||
'salt': salt,
|
||||
'keyBytesCount': keyBytesCount,
|
||||
'iterations': iterations,
|
||||
'algorithm': algorithm,
|
||||
},
|
||||
);
|
||||
} catch (e, s) {
|
||||
NativeCryptoException.convertPlatformException(e, s);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -65,15 +77,19 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform {
|
||||
Uint8List data,
|
||||
Uint8List key,
|
||||
String algorithm,
|
||||
) {
|
||||
return channel.invokeListMethod(
|
||||
'encryptAsList',
|
||||
<String, dynamic>{
|
||||
'data': data,
|
||||
'key': key,
|
||||
'algorithm': algorithm,
|
||||
},
|
||||
);
|
||||
) async {
|
||||
try {
|
||||
return await channel.invokeListMethod(
|
||||
'encryptAsList',
|
||||
<String, dynamic>{
|
||||
'data': data,
|
||||
'key': key,
|
||||
'algorithm': algorithm,
|
||||
},
|
||||
);
|
||||
} catch (e, s) {
|
||||
NativeCryptoException.convertPlatformException(e, s);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -81,15 +97,19 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform {
|
||||
List<Uint8List> data,
|
||||
Uint8List key,
|
||||
String algorithm,
|
||||
) {
|
||||
return channel.invokeMethod<Uint8List>(
|
||||
'decryptAsList',
|
||||
<String, dynamic>{
|
||||
'data': data,
|
||||
'key': key,
|
||||
'algorithm': algorithm,
|
||||
},
|
||||
);
|
||||
) async {
|
||||
try {
|
||||
return await channel.invokeMethod<Uint8List>(
|
||||
'decryptAsList',
|
||||
<String, dynamic>{
|
||||
'data': data,
|
||||
'key': key,
|
||||
'algorithm': algorithm,
|
||||
},
|
||||
);
|
||||
} catch (e, s) {
|
||||
NativeCryptoException.convertPlatformException(e, s);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -97,15 +117,19 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform {
|
||||
Uint8List data,
|
||||
Uint8List key,
|
||||
String algorithm,
|
||||
) {
|
||||
return channel.invokeMethod<Uint8List>(
|
||||
'encrypt',
|
||||
<String, dynamic>{
|
||||
'data': data,
|
||||
'key': key,
|
||||
'algorithm': algorithm,
|
||||
},
|
||||
);
|
||||
) async {
|
||||
try {
|
||||
return await channel.invokeMethod<Uint8List>(
|
||||
'encrypt',
|
||||
<String, dynamic>{
|
||||
'data': data,
|
||||
'key': key,
|
||||
'algorithm': algorithm,
|
||||
},
|
||||
);
|
||||
} catch (e, s) {
|
||||
NativeCryptoException.convertPlatformException(e, s);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -113,14 +137,18 @@ class MethodChannelNativeCrypto extends NativeCryptoPlatform {
|
||||
Uint8List data,
|
||||
Uint8List key,
|
||||
String algorithm,
|
||||
) {
|
||||
return channel.invokeMethod<Uint8List>(
|
||||
'decrypt',
|
||||
<String, dynamic>{
|
||||
'data': data,
|
||||
'key': key,
|
||||
'algorithm': algorithm,
|
||||
},
|
||||
);
|
||||
) async {
|
||||
try {
|
||||
return await channel.invokeMethod<Uint8List>(
|
||||
'decrypt',
|
||||
<String, dynamic>{
|
||||
'data': data,
|
||||
'key': key,
|
||||
'algorithm': algorithm,
|
||||
},
|
||||
);
|
||||
} catch (e, s) {
|
||||
NativeCryptoException.convertPlatformException(e, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,51 +3,151 @@
|
||||
// -----
|
||||
// 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';
|
||||
|
||||
/// Catches a [PlatformException] and returns an [Exception].
|
||||
///
|
||||
/// If the [Exception] is a [PlatformException],
|
||||
/// a [NativeCryptoException] is returned.
|
||||
Never convertPlatformException(Object exception, StackTrace stackTrace) {
|
||||
if (exception is! Exception || exception is! PlatformException) {
|
||||
Error.throwWithStackTrace(exception, stackTrace);
|
||||
/// 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;
|
||||
}
|
||||
|
||||
Error.throwWithStackTrace(
|
||||
platformExceptionToNativeCryptoException(exception, stackTrace),
|
||||
stackTrace,
|
||||
);
|
||||
}
|
||||
/// Catches a [PlatformException] and returns an [Exception].
|
||||
///
|
||||
/// 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].
|
||||
///
|
||||
/// A [PlatformException] can only be converted to a [NativeCryptoException]
|
||||
/// 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;
|
||||
Error.throwWithStackTrace(
|
||||
NativeCryptoException.fromPlatformException(exception, stackTrace),
|
||||
stackTrace,
|
||||
);
|
||||
}
|
||||
|
||||
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