refactor: (WIP) optimize exceptions and bytearray
This commit is contained in:
parent
9bfe969c7d
commit
6939a8df7e
@ -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: 25/05/2022 10:48:20
|
// Last Modified: 26/05/2022 12:10:42
|
||||||
// -----
|
// -----
|
||||||
// Copyright (c) 2021
|
// Copyright (c) 2021
|
||||||
|
|
||||||
@ -23,7 +23,6 @@ export 'src/kdf/kdf.dart';
|
|||||||
export 'src/keys/keys.dart';
|
export 'src/keys/keys.dart';
|
||||||
// Utils
|
// Utils
|
||||||
export 'src/utils/cipher_algorithm.dart';
|
export 'src/utils/cipher_algorithm.dart';
|
||||||
export 'src/utils/convert.dart';
|
|
||||||
export 'src/utils/hash_algorithm.dart';
|
export 'src/utils/hash_algorithm.dart';
|
||||||
export 'src/utils/kdf_algorithm.dart';
|
export 'src/utils/kdf_algorithm.dart';
|
||||||
|
|
||||||
|
@ -3,81 +3,144 @@
|
|||||||
// -----
|
// -----
|
||||||
// File: cipher_text.dart
|
// File: cipher_text.dart
|
||||||
// Created Date: 16/12/2021 16:59:53
|
// Created Date: 16/12/2021 16:59:53
|
||||||
// Last Modified: 24/05/2022 21:27:44
|
// Last Modified: 26/05/2022 16:22:49
|
||||||
// -----
|
// -----
|
||||||
// Copyright (c) 2021
|
// Copyright (c) 2021
|
||||||
|
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:native_crypto/src/interfaces/byte_array.dart';
|
import 'package:native_crypto/src/utils/cipher_algorithm.dart';
|
||||||
|
import 'package:native_crypto/src/utils/extensions.dart';
|
||||||
|
import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
|
||||||
|
|
||||||
class CipherText extends ByteArray {
|
/// Represents a cipher text in Native Crypto.
|
||||||
|
///
|
||||||
|
/// It is represented as a [List] of [Uint8List] like:
|
||||||
|
/// ```txt
|
||||||
|
/// [[NONCE], [MESSAGE + TAG]]
|
||||||
|
/// ```
|
||||||
|
/// where:
|
||||||
|
/// - `[NONCE]` is a [Uint8List] of length [CipherText.ivLength]
|
||||||
|
/// - `[MESSAGE + TAG]` is a [Uint8List] of length [CipherText.dataLength]
|
||||||
|
///
|
||||||
|
/// To
|
||||||
|
///
|
||||||
|
/// So accessing just the Message or just the Tag is costly and should be
|
||||||
|
/// done only when needed.
|
||||||
|
class CipherText {
|
||||||
final int _ivLength;
|
final int _ivLength;
|
||||||
final int _dataLength;
|
final int _messageLength;
|
||||||
final int _tagLength;
|
final int _tagLength;
|
||||||
|
|
||||||
final Uint8List _iv;
|
final CipherAlgorithm? _cipherAlgorithm;
|
||||||
|
|
||||||
CipherText(Uint8List iv, Uint8List data, Uint8List? tag)
|
final Uint8List? _iv;
|
||||||
: _ivLength = iv.length,
|
final Uint8List? _data; // Contains the message + tag (if any)
|
||||||
_dataLength = data.length,
|
|
||||||
_tagLength = tag?.length ?? 0,
|
|
||||||
_iv = iv,
|
|
||||||
super((tag != null) ? Uint8List.fromList(data + tag) : data);
|
|
||||||
|
|
||||||
CipherText.fromBytes(
|
CipherText._(
|
||||||
Uint8List bytes, {
|
this._ivLength,
|
||||||
required int ivLength,
|
this._messageLength,
|
||||||
required int dataLength,
|
this._tagLength,
|
||||||
int tagLength = 0,
|
this._cipherAlgorithm,
|
||||||
}) : _ivLength = ivLength,
|
this._iv,
|
||||||
_dataLength = dataLength,
|
this._data,
|
||||||
_tagLength = tagLength,
|
);
|
||||||
_iv = bytes.sublist(0, ivLength),
|
|
||||||
super(bytes.sublist(ivLength, bytes.length - tagLength));
|
|
||||||
|
|
||||||
const CipherText.fromIvAndBytes(
|
/// Gets the [CipherAlgorithm] used to encrypt the [CipherText].
|
||||||
Uint8List iv,
|
CipherAlgorithm get cipherAlgorithm {
|
||||||
super.data, {
|
if (_cipherAlgorithm.isNotNull) {
|
||||||
required int dataLength,
|
return _cipherAlgorithm!;
|
||||||
int tagLength = 0,
|
} else {
|
||||||
}) : _ivLength = iv.length,
|
throw NativeCryptoException(
|
||||||
_dataLength = dataLength,
|
message: 'Cipher algorithm is not specified',
|
||||||
_tagLength = tagLength,
|
code: NativeCryptoExceptionCode.invalid_cipher.code,
|
||||||
_iv = iv;
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CipherText.fromPairIvAndBytes(
|
/// Gets the [Uint8List] of the [CipherText]'s IV.
|
||||||
List<Uint8List> pair, {
|
Uint8List get iv {
|
||||||
required int dataLength,
|
if (_iv.isNotNull) {
|
||||||
int tagLength = 0,
|
return _iv!;
|
||||||
}) : _ivLength = pair.first.length,
|
} else {
|
||||||
_dataLength = dataLength,
|
throw NativeCryptoException(
|
||||||
_tagLength = tagLength,
|
message: 'IV is not specified',
|
||||||
_iv = pair.first,
|
code: NativeCryptoExceptionCode.invalid_data.code,
|
||||||
super(pair.last);
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the CipherText IV.
|
/// Gets the length of the [CipherText]'s IV.
|
||||||
Uint8List get iv => _iv;
|
|
||||||
|
|
||||||
/// Gets the CipherText data.
|
|
||||||
Uint8List get data => _tagLength > 0
|
|
||||||
? bytes.sublist(0, _dataLength - _tagLength)
|
|
||||||
: bytes;
|
|
||||||
|
|
||||||
/// Gets the CipherText tag.
|
|
||||||
Uint8List get tag => _tagLength > 0
|
|
||||||
? bytes.sublist(_dataLength - _tagLength, _dataLength)
|
|
||||||
: Uint8List(0);
|
|
||||||
|
|
||||||
/// Gets the CipherText data and tag.
|
|
||||||
Uint8List get payload => bytes;
|
|
||||||
|
|
||||||
/// Gets the CipherText IV length.
|
|
||||||
int get ivLength => _ivLength;
|
int get ivLength => _ivLength;
|
||||||
|
|
||||||
/// Gets the CipherText data length.
|
/// Gets the [Uint8List] of the [CipherText]'s data.
|
||||||
int get dataLength => _dataLength;
|
Uint8List get data {
|
||||||
|
if (_data.isNotNull) {
|
||||||
|
return _data!;
|
||||||
|
} else {
|
||||||
|
throw NativeCryptoException(
|
||||||
|
message: 'Data is not specified',
|
||||||
|
code: NativeCryptoExceptionCode.invalid_data.code,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the CipherText tag length.
|
/// Gets the length of the [CipherText]'s data.
|
||||||
int get tagLength => _tagLength;
|
int get dataLength => _messageLength + _tagLength;
|
||||||
|
|
||||||
|
// CipherText.fromBytes(
|
||||||
|
// Uint8List bytes, {
|
||||||
|
// required int ivLength,
|
||||||
|
// required int dataLength,
|
||||||
|
// int tagLength = 0,
|
||||||
|
// }) : _ivLength = ivLength,
|
||||||
|
// _dataLength = dataLength,
|
||||||
|
// _tagLength = tagLength,
|
||||||
|
// _iv = bytes.sublist(0, ivLength),
|
||||||
|
// super(bytes.sublist(ivLength, bytes.length - tagLength));
|
||||||
|
|
||||||
|
// const CipherText.fromIvAndBytes(
|
||||||
|
// Uint8List iv,
|
||||||
|
// super.data, {
|
||||||
|
// required int dataLength,
|
||||||
|
// int tagLength = 0,
|
||||||
|
// }) : _ivLength = iv.length,
|
||||||
|
// _dataLength = dataLength,
|
||||||
|
// _tagLength = tagLength,
|
||||||
|
// _iv = iv;
|
||||||
|
|
||||||
|
// CipherText.fromPairIvAndBytes(
|
||||||
|
// List<Uint8List> pair, {
|
||||||
|
// required int dataLength,
|
||||||
|
// int tagLength = 0,
|
||||||
|
// }) : _ivLength = pair.first.length,
|
||||||
|
// _dataLength = dataLength,
|
||||||
|
// _tagLength = tagLength,
|
||||||
|
// _iv = pair.first,
|
||||||
|
// super(pair.last);
|
||||||
|
|
||||||
|
// /// Gets the CipherText IV.
|
||||||
|
// Uint8List get iv => _iv;
|
||||||
|
|
||||||
|
// /// Gets the CipherText data.
|
||||||
|
// Uint8List get data => _tagLength > 0
|
||||||
|
// ? bytes.sublist(0, _dataLength - _tagLength)
|
||||||
|
// : bytes;
|
||||||
|
|
||||||
|
// /// Gets the CipherText tag.
|
||||||
|
// Uint8List get tag => _tagLength > 0
|
||||||
|
// ? bytes.sublist(_dataLength - _tagLength, _dataLength)
|
||||||
|
// : Uint8List(0);
|
||||||
|
|
||||||
|
// /// Gets the CipherText data and tag.
|
||||||
|
// Uint8List get payload => bytes;
|
||||||
|
|
||||||
|
// /// Gets the CipherText IV length.
|
||||||
|
// int get ivLength => _ivLength;
|
||||||
|
|
||||||
|
// /// Gets the CipherText data length.
|
||||||
|
// int get dataLength => _dataLength;
|
||||||
|
|
||||||
|
// /// Gets the CipherText tag length.
|
||||||
|
// int get tagLength => _tagLength;
|
||||||
}
|
}
|
||||||
|
89
packages/native_crypto/lib/src/core/cipher_text_wrapper.dart
Normal file
89
packages/native_crypto/lib/src/core/cipher_text_wrapper.dart
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
// Author: Hugo Pointcheval
|
||||||
|
// Email: git@pcl.ovh
|
||||||
|
// -----
|
||||||
|
// File: cipher_text_wrapper.dart
|
||||||
|
// Created Date: 26/05/2022 14:27:32
|
||||||
|
// Last Modified: 26/05/2022 15:53:46
|
||||||
|
// -----
|
||||||
|
// Copyright (c) 2022
|
||||||
|
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:native_crypto/native_crypto.dart';
|
||||||
|
import 'package:native_crypto/src/utils/extensions.dart';
|
||||||
|
|
||||||
|
class CipherTextWrapper {
|
||||||
|
final CipherText? _single;
|
||||||
|
final List<CipherText>? _list;
|
||||||
|
|
||||||
|
CipherTextWrapper._(this._single, this._list);
|
||||||
|
|
||||||
|
factory CipherTextWrapper.single(CipherText cipherText) =>
|
||||||
|
CipherTextWrapper._(cipherText, null);
|
||||||
|
|
||||||
|
factory CipherTextWrapper.list(List<CipherText> cipherTexts) =>
|
||||||
|
CipherTextWrapper._(null, cipherTexts);
|
||||||
|
|
||||||
|
factory CipherTextWrapper.fromBytes(
|
||||||
|
// Uint8List bytes, {
|
||||||
|
// required int ivLength,
|
||||||
|
// required int dataLength,
|
||||||
|
// int tagLength = 0,
|
||||||
|
// int? chunkSize,
|
||||||
|
// }
|
||||||
|
) {
|
||||||
|
// TODO(hpcl): implement fromBytes
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get isSingle => _single.isNotNull;
|
||||||
|
bool get isList => _list.isNotNull;
|
||||||
|
|
||||||
|
/// Gets the [CipherText] if it's a single one.
|
||||||
|
///
|
||||||
|
/// Throws [NativeCryptoException] with
|
||||||
|
/// [NativeCryptoExceptionCode.invalid_data] if it's not a single one.
|
||||||
|
CipherText get single {
|
||||||
|
if (isSingle) {
|
||||||
|
return _single!;
|
||||||
|
} else {
|
||||||
|
throw NativeCryptoException(
|
||||||
|
message: 'CipherTextWrapper is not single',
|
||||||
|
code: NativeCryptoExceptionCode.invalid_data.code,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the [List] of [CipherText] if it's a list.
|
||||||
|
///
|
||||||
|
/// Throws [NativeCryptoException] with
|
||||||
|
/// [NativeCryptoExceptionCode.invalid_data] if it's not a list.
|
||||||
|
List<CipherText> get list {
|
||||||
|
if (isList) {
|
||||||
|
return _list!;
|
||||||
|
} else {
|
||||||
|
throw NativeCryptoException(
|
||||||
|
message: 'CipherTextWrapper is not list',
|
||||||
|
code: NativeCryptoExceptionCode.invalid_data.code,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the raw [Uint8List] of the [CipherText] or [List] of [CipherText].
|
||||||
|
Uint8List get raw {
|
||||||
|
if (isSingle) {
|
||||||
|
return single.bytes;
|
||||||
|
} else {
|
||||||
|
return list.map((cipherText) => cipherText.bytes).toList().sum();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int get chunkCount {
|
||||||
|
_single.isNull;
|
||||||
|
if (_single.isNotNull) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return _list?.length ?? 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,47 +3,58 @@
|
|||||||
// -----
|
// -----
|
||||||
// File: byte_array.dart
|
// File: byte_array.dart
|
||||||
// Created Date: 16/12/2021 17:54:16
|
// Created Date: 16/12/2021 17:54:16
|
||||||
// Last Modified: 23/05/2022 23:07:03
|
// Last Modified: 26/05/2022 14:25:05
|
||||||
// -----
|
// -----
|
||||||
// Copyright (c) 2021
|
// Copyright (c) 2021
|
||||||
|
|
||||||
import 'dart:convert' as convert;
|
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:native_crypto/src/utils/convert.dart';
|
import 'package:native_crypto/src/utils/encoding.dart';
|
||||||
|
import 'package:native_crypto/src/utils/extensions.dart';
|
||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
abstract class ByteArray {
|
abstract class ByteArray {
|
||||||
final Uint8List _bytes;
|
final Uint8List _bytes;
|
||||||
|
|
||||||
|
/// Creates a [ByteArray] from a [Uint8List].
|
||||||
const ByteArray(this._bytes);
|
const ByteArray(this._bytes);
|
||||||
|
|
||||||
/// Creates an ByteArray object from a hexdecimal string.
|
/// Creates a [ByteArray] object from a hexdecimal string.
|
||||||
ByteArray.fromBase16(String encoded)
|
ByteArray.fromBase16(String encoded)
|
||||||
: _bytes = Convert.decodeHexString(encoded);
|
: _bytes = encoded.toBytes(from: Encoding.base16);
|
||||||
|
|
||||||
/// Creates an ByteArray object from a Base64 string.
|
/// Creates a [ByteArray] object from a Base64 string.
|
||||||
ByteArray.fromBase64(String encoded)
|
ByteArray.fromBase64(String encoded)
|
||||||
: _bytes = convert.base64.decode(encoded);
|
: _bytes = encoded.toBytes(from: Encoding.base64);
|
||||||
|
|
||||||
/// Creates an ByteArray object from a UTF-8 string.
|
/// Creates a [ByteArray] object from an UTF-8 string.
|
||||||
ByteArray.fromUtf8(String input)
|
ByteArray.fromUtf8(String encoded)
|
||||||
: _bytes = Uint8List.fromList(convert.utf8.encode(input));
|
: _bytes = encoded.toBytes(from: Encoding.utf8);
|
||||||
|
|
||||||
/// Creates an ByteArray object from a length.
|
/// Creates a [ByteArray] object from an UTF-16 string.
|
||||||
|
ByteArray.fromUtf16(String encoded) : _bytes = encoded.toBytes();
|
||||||
|
|
||||||
|
/// Creates an empty [ByteArray] object from a length.
|
||||||
ByteArray.fromLength(int length) : _bytes = Uint8List(length);
|
ByteArray.fromLength(int length) : _bytes = Uint8List(length);
|
||||||
|
|
||||||
/// Gets the ByteArray bytes.
|
/// Creates a [ByteArray] object from a [List] of [int].
|
||||||
// ignore: unnecessary_getters_setters
|
ByteArray.fromList(List<int> list) : _bytes = list.toTypedList();
|
||||||
|
|
||||||
|
/// Gets the [ByteArray] bytes.
|
||||||
Uint8List get bytes => _bytes;
|
Uint8List get bytes => _bytes;
|
||||||
|
|
||||||
/// Gets the ByteArray bytes as a Hexadecimal representation.
|
/// Gets the [ByteArray] bytes as a Hexadecimal representation.
|
||||||
String get base16 =>
|
String get base16 => _bytes.toStr(to: Encoding.base16);
|
||||||
_bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join();
|
|
||||||
|
|
||||||
/// Gets the ByteArray bytes as a Base64 representation.
|
/// Gets the [ByteArray] bytes as a Base64 representation.
|
||||||
String get base64 => convert.base64.encode(_bytes);
|
String get base64 => _bytes.toStr(to: Encoding.base64);
|
||||||
|
|
||||||
|
/// Gets the [ByteArray] bytes as an UTF-8 representation.
|
||||||
|
String get utf8 => _bytes.toStr(to: Encoding.utf8);
|
||||||
|
|
||||||
|
/// Gets the [ByteArray] bytes as an UTF-16 representation.
|
||||||
|
String get utf16 => _bytes.toStr();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
// -----
|
// -----
|
||||||
// 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: 25/05/2022 10:45:55
|
// Last Modified: 26/05/2022 11:56:06
|
||||||
// -----
|
// -----
|
||||||
// Copyright (c) 2021
|
// Copyright (c) 2021
|
||||||
|
|
||||||
@ -24,13 +24,22 @@ class SecretKey extends Key {
|
|||||||
|
|
||||||
static Future<SecretKey> fromSecureRandom(int bitsCount) async {
|
static Future<SecretKey> fromSecureRandom(int bitsCount) async {
|
||||||
try {
|
try {
|
||||||
final Uint8List _key =
|
final Uint8List? _key = await platform.generateSecretKey(bitsCount);
|
||||||
(await platform.generateSecretKey(bitsCount)) ?? Uint8List(0);
|
|
||||||
|
if (_key == null || _key.isEmpty) {
|
||||||
|
throw const KeyException(
|
||||||
|
message: 'Could not generate secret key, platform returned null',
|
||||||
|
code: 'platform_returned_null',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return SecretKey(_key);
|
return SecretKey(_key);
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
|
if (e is KeyException) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
throw KeyException(
|
throw KeyException(
|
||||||
message: 'Failed to generate a secret key!',
|
message: '$e',
|
||||||
code: 'failed_to_generate_secret_key',
|
code: 'failed_to_generate_secret_key',
|
||||||
stackTrace: s,
|
stackTrace: s,
|
||||||
);
|
);
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
// Author: Hugo Pointcheval
|
|
||||||
// Email: git@pcl.ovh
|
|
||||||
// -----
|
|
||||||
// File: convert.dart
|
|
||||||
// Created Date: 16/12/2021 16:28:00
|
|
||||||
// Last Modified: 23/05/2022 22:39:19
|
|
||||||
// -----
|
|
||||||
// Copyright (c) 2021
|
|
||||||
|
|
||||||
import 'dart:typed_data';
|
|
||||||
|
|
||||||
abstract class Convert {
|
|
||||||
static Uint8List decodeHexString(String input) {
|
|
||||||
assert(input.length.isEven, 'Input needs to be an even length.');
|
|
||||||
|
|
||||||
return Uint8List.fromList(
|
|
||||||
List.generate(
|
|
||||||
input.length ~/ 2,
|
|
||||||
(i) => int.parse(input.substring(i * 2, (i * 2) + 2), radix: 16),
|
|
||||||
).toList(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
10
packages/native_crypto/lib/src/utils/encoding.dart
Normal file
10
packages/native_crypto/lib/src/utils/encoding.dart
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// Author: Hugo Pointcheval
|
||||||
|
// Email: git@pcl.ovh
|
||||||
|
// -----
|
||||||
|
// File: encoding.dart
|
||||||
|
// Created Date: 26/05/2022 12:12:34
|
||||||
|
// Last Modified: 26/05/2022 12:18:09
|
||||||
|
// -----
|
||||||
|
// Copyright (c) 2022
|
||||||
|
|
||||||
|
enum Encoding { utf8, utf16, base64, base16 }
|
95
packages/native_crypto/lib/src/utils/extensions.dart
Normal file
95
packages/native_crypto/lib/src/utils/extensions.dart
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
// Author: Hugo Pointcheval
|
||||||
|
// Email: git@pcl.ovh
|
||||||
|
// -----
|
||||||
|
// File: extensions.dart
|
||||||
|
// Created Date: 26/05/2022 12:12:48
|
||||||
|
// Last Modified: 26/05/2022 15:49:38
|
||||||
|
// -----
|
||||||
|
// Copyright (c) 2022
|
||||||
|
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:developer' as developer;
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:native_crypto/src/utils/encoding.dart';
|
||||||
|
|
||||||
|
extension ObjectX on Object? {
|
||||||
|
/// Returns `true` if the object is `null`.
|
||||||
|
bool get isNull => this == null;
|
||||||
|
|
||||||
|
/// Returns `true` if the object is **not** `null`.
|
||||||
|
bool get isNotNull => this != null;
|
||||||
|
|
||||||
|
/// Prints the object to the console.
|
||||||
|
void log() => developer.log(toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ListIntX on List<int> {
|
||||||
|
/// Converts a [List] of int to a [Uint8List].
|
||||||
|
Uint8List toTypedList() => Uint8List.fromList(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ListUint8ListX on List<Uint8List> {
|
||||||
|
/// Reduce a [List] of [Uint8List] to a [Uint8List].
|
||||||
|
|
||||||
|
Uint8List sum() {
|
||||||
|
for (var i = 1; i < length; i++) {
|
||||||
|
first.addAll(this[i]);
|
||||||
|
removeAt(i);
|
||||||
|
}
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension StringX on String {
|
||||||
|
/// Converts a [String] to a [Uint8List] using the specified [Encoding].
|
||||||
|
Uint8List toBytes({final Encoding from = Encoding.utf16}) {
|
||||||
|
Uint8List bytes;
|
||||||
|
switch (from) {
|
||||||
|
case Encoding.utf8:
|
||||||
|
bytes = utf8.encode(this).toTypedList();
|
||||||
|
break;
|
||||||
|
case Encoding.utf16:
|
||||||
|
bytes = runes.toList().toTypedList();
|
||||||
|
break;
|
||||||
|
case Encoding.base64:
|
||||||
|
bytes = base64.decode(this);
|
||||||
|
break;
|
||||||
|
case Encoding.base16:
|
||||||
|
assert(length.isEven, 'String needs to be an even length.');
|
||||||
|
bytes = List.generate(
|
||||||
|
length ~/ 2,
|
||||||
|
(i) => int.parse(substring(i * 2, (i * 2) + 2), radix: 16),
|
||||||
|
).toList().toTypedList();
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Uint8ListX on Uint8List {
|
||||||
|
/// Converts a [Uint8List] to a [String] using the specified [Encoding].
|
||||||
|
String toStr({final Encoding to = Encoding.utf16}) {
|
||||||
|
String str;
|
||||||
|
switch (to) {
|
||||||
|
case Encoding.utf8:
|
||||||
|
str = utf8.decode(this);
|
||||||
|
break;
|
||||||
|
case Encoding.utf16:
|
||||||
|
str = String.fromCharCodes(this);
|
||||||
|
break;
|
||||||
|
case Encoding.base64:
|
||||||
|
str = base64.encode(this);
|
||||||
|
break;
|
||||||
|
case Encoding.base16:
|
||||||
|
str = List.generate(
|
||||||
|
length,
|
||||||
|
(i) => this[i].toRadixString(16).padLeft(2, '0'),
|
||||||
|
).join();
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a concatenation of this with the other [Uint8List].
|
||||||
|
Uint8List operator +(final Uint8List other) =>
|
||||||
|
[...this, ...other].toTypedList();
|
||||||
|
}
|
@ -3,21 +3,41 @@
|
|||||||
// -----
|
// -----
|
||||||
// File: exception.dart
|
// File: exception.dart
|
||||||
// Created Date: 24/05/2022 18:54:48
|
// Created Date: 24/05/2022 18:54:48
|
||||||
// Last Modified: 25/05/2022 10:43:29
|
// Last Modified: 26/05/2022 15:36:56
|
||||||
// -----
|
// -----
|
||||||
// Copyright (c) 2022
|
// Copyright (c) 2022
|
||||||
|
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
enum NativeCryptoExceptionCode {
|
||||||
|
unknown,
|
||||||
|
not_implemented,
|
||||||
|
invalid_argument,
|
||||||
|
invalid_key,
|
||||||
|
invalid_key_length,
|
||||||
|
invalid_algorithm,
|
||||||
|
invalid_padding,
|
||||||
|
invalid_mode,
|
||||||
|
invalid_cipher,
|
||||||
|
invalid_data,
|
||||||
|
platform_not_supported,
|
||||||
|
platform_returned_invalid_data,
|
||||||
|
platform_returned_empty_data,
|
||||||
|
platform_returned_null;
|
||||||
|
|
||||||
|
String get code => toString().split('.').last.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
class NativeCryptoException implements Exception {
|
class NativeCryptoException implements Exception {
|
||||||
const NativeCryptoException({
|
NativeCryptoException({
|
||||||
this.message,
|
this.message,
|
||||||
String? code,
|
String? code,
|
||||||
this.stackTrace,
|
this.stackTrace,
|
||||||
// ignore: unnecessary_this
|
}) : code = code ?? NativeCryptoExceptionCode.unknown.code;
|
||||||
}) : this.code = code ?? 'unknown';
|
|
||||||
|
|
||||||
/// The long form message of the exception.
|
/// The long form message of the exception.
|
||||||
final String? message;
|
final String? message;
|
||||||
@ -73,7 +93,7 @@ class NativeCryptoException implements Exception {
|
|||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
String code = 'unknown';
|
String code = NativeCryptoExceptionCode.unknown.code;
|
||||||
String message = platformException.message ?? '';
|
String message = platformException.message ?? '';
|
||||||
|
|
||||||
if (details != null) {
|
if (details != null) {
|
||||||
@ -103,51 +123,3 @@ class NativeCryptoException implements Exception {
|
|||||||
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||||
int get hashCode => message.hashCode ^ code.hashCode ^ stackTrace.hashCode;
|
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