Fix/Update #1
| @ -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