diff --git a/lib/src/asym/RSA.dart b/lib/src/asym/RSA.dart index dffdb6d..d09bd4d 100644 --- a/lib/src/asym/RSA.dart +++ b/lib/src/asym/RSA.dart @@ -14,10 +14,10 @@ class RSAKeyEncapsulationMechanism implements KeyEncapsulationMechanism { PrivateKey _privateKey; @override - String get algorithm => "RSA"; + KemAlgorithm get algorithm => KemAlgorithm.RSA; @override - Object get options => throw UnimplementedError(); + Object get options => null; @override bool get isInitialized => _isInit; diff --git a/lib/src/cipher.dart b/lib/src/cipher.dart index a5ef9d6..335505d 100644 --- a/lib/src/cipher.dart +++ b/lib/src/cipher.dart @@ -5,6 +5,9 @@ import 'dart:typed_data'; import 'key.dart'; +/// Represents different cipher algorithms +enum CipherAlgorithm { AES, BlowFish } + /// Represents different block cipher modes enum BlockCipherMode { ECB, CBC, CFB, GCM, CGM } @@ -18,7 +21,7 @@ enum Padding { ANSI_X923, PKCS5, PKCS7, None } /// be followed as a procedure. abstract class Cipher { /// Returns the standard algorithm name for this cipher - String get algorithm; + CipherAlgorithm get algorithm; /// Returns the secret key used for this cipher SecretKey get secretKey; @@ -47,7 +50,7 @@ abstract class Cipher { /// It's the result of an encryption. abstract class CipherText { /// Returns the standard algorithm name used for this ciphertext - String get algorithm; + CipherAlgorithm get algorithm; /// Returns the data of this ciphertext Uint8List get bytes; diff --git a/lib/src/exceptions.dart b/lib/src/exceptions.dart index c9df2c9..1001df1 100644 --- a/lib/src/exceptions.dart +++ b/lib/src/exceptions.dart @@ -10,6 +10,14 @@ class KeyException extends NativeCryptoException { KeyException(message) : super(message); } +class UtilsException extends NativeCryptoException { + UtilsException(message) : super(message); +} + +class KeyDerivationException extends NativeCryptoException { + KeyDerivationException(message) : super(message); +} + class CipherInitException extends NativeCryptoException { CipherInitException(message) : super(message); } @@ -18,6 +26,10 @@ class KemInitException extends NativeCryptoException { KemInitException(message) : super(message); } +class DigestInitException extends NativeCryptoException { + DigestInitException(message) : super(message); +} + class EncryptionException extends NativeCryptoException { EncryptionException(message) : super(message); } diff --git a/lib/src/kem.dart b/lib/src/kem.dart index e91d557..e6a23dd 100644 --- a/lib/src/kem.dart +++ b/lib/src/kem.dart @@ -5,11 +5,13 @@ import 'dart:typed_data'; import 'key.dart'; +enum KemAlgorithm { RSA, ECDH } + enum KemMode { ENCAPSULATION, DECAPSULATION } abstract class KeyEncapsulationMechanism { /// Returns the standard algorithm name for this kem - String get algorithm; + KemAlgorithm get algorithm; /// Returns the parameters used for this kem Object get options; @@ -40,7 +42,7 @@ abstract class KeyEncapsulationMechanism { abstract class Encapsulation { /// Returns the standard algorithm name used for this encapsulation - String get algorithm; + KemAlgorithm get algorithm; /// Returns the secret key used in this encapsulation SecretKey get secretKey; diff --git a/lib/src/sym/AES.dart b/lib/src/sym/AES.dart index 8a9ea4b..1e15347 100644 --- a/lib/src/sym/AES.dart +++ b/lib/src/sym/AES.dart @@ -7,6 +7,7 @@ import '../cipher.dart'; import '../exceptions.dart'; import '../key.dart'; import '../platform.dart'; +import '../utils.dart'; /// Defines all available key sizes. enum AESKeySize { bits128, bits192, bits256 } @@ -21,7 +22,7 @@ class AESCipher implements Cipher { ]; @override - String get algorithm => "AES"; + CipherAlgorithm get algorithm => CipherAlgorithm.AES; @override SecretKey get secretKey => _sk; @@ -70,15 +71,15 @@ class AESCipher implements Cipher { throw CipherInitException('Invalid key size.'); } List c = - await Platform().encrypt(data, _sk.encoded, "AES", _params); + await Platform().encrypt(data, _sk.encoded, algorithm, _params); return AESCipherText(c[0], c[1]); } @override Future decrypt(CipherText cipherText) async { - if (cipherText.algorithm != "AES") { + if (cipherText.algorithm != CipherAlgorithm.AES) { throw DecryptionException("This cipher text's algorithm is not AES: " + - cipherText.algorithm + + cipherText.algorithm.name + "\nYou must use an AESCipherText."); } else if (!_isInit) { throw CipherInitException('Cipher not properly initialized.'); @@ -87,7 +88,7 @@ class AESCipher implements Cipher { } List payload = [cipherText.bytes, cipherText.iv]; Uint8List d = - await Platform().decrypt(payload, _sk.encoded, "AES", _params); + await Platform().decrypt(payload, _sk.encoded, algorithm, _params); return d; } } @@ -97,7 +98,7 @@ class AESCipherText implements CipherText { Uint8List _iv; @override - String get algorithm => "AES"; + CipherAlgorithm get algorithm => CipherAlgorithm.AES; @override Uint8List get bytes => _bytes; diff --git a/lib/src/utils.dart b/lib/src/utils.dart new file mode 100644 index 0000000..c037e45 --- /dev/null +++ b/lib/src/utils.dart @@ -0,0 +1,141 @@ +// Copyright (c) 2020 +// Author: Hugo Pointcheval + +import 'package:flutter/foundation.dart'; + +import 'cipher.dart'; +import 'digest.dart'; +import 'exceptions.dart'; +import 'kem.dart'; +import 'keyderivation.dart'; + +extension HashAlgorithmExtension on HashAlgorithm { + String get name => describeEnum(this).toLowerCase(); +} + +extension KdfAlgorithmExtension on KdfAlgorithm { + String get name => describeEnum(this).toLowerCase(); +} + +extension CipherAlgorithmExtension on CipherAlgorithm { + String get name => describeEnum(this).toLowerCase(); +} + +extension KemAlgorithmExtension on KemAlgorithm { + String get name => describeEnum(this).toLowerCase(); +} + +extension BlockCipherModeExtension on BlockCipherMode { + String get name => describeEnum(this).toLowerCase(); +} + +extension PaddingExtension on Padding { + String get name => describeEnum(this).toLowerCase(); +} + +class Utils { + /// Returns [HashAlgorithm] from his name. + static HashAlgorithm getHashAlgorithm(String algorithm) { + String _query = algorithm.toLowerCase(); + for (HashAlgorithm h in HashAlgorithm.values) { + if (_query == h.name) { + return h; + } + } + throw UtilsException("Unknown hash algorithm!"); + } + + /// Returns all available [HashAlgorithm] as String list + static List getAvailableHashAlgorithms() { + List _res = []; + for (HashAlgorithm h in HashAlgorithm.values) { + _res.add(h.name); + } + return _res; + } + + /// Returns [KdfAlgorithm] from his name. + static KdfAlgorithm getKdfAlgorithm(String algorithm) { + String _query = algorithm.toLowerCase(); + for (KdfAlgorithm h in KdfAlgorithm.values) { + if (_query == h.name) { + return h; + } + } + throw UtilsException("Unknown key derivation algorithm!"); + } + + /// Returns all available [KdfAlgorithm] as String list + static List getAvailableKdfAlgorithms() { + List _res = []; + for (KdfAlgorithm h in KdfAlgorithm.values) { + _res.add(h.name); + } + return _res; + } + + /// Returns [CipherAlgorithm] from his name. + static CipherAlgorithm getCipherAlgorithm(String algorithm) { + String _query = algorithm.toLowerCase(); + for (CipherAlgorithm c in CipherAlgorithm.values) { + if (_query == c.name) { + return c; + } + } + throw UtilsException("Unknown cipher algorithm!"); + } + + /// Returns all available [CipherAlgorithm] as String list + static List getAvailableCipherAlgorithms() { + List _res = []; + for (CipherAlgorithm c in CipherAlgorithm.values) { + _res.add(c.name); + } + return _res; + } + + /// Returns [KemAlgorithm] from his name. + static KemAlgorithm getKemAlgorithm(String algorithm) { + String _query = algorithm.toLowerCase(); + for (KemAlgorithm k in KemAlgorithm.values) { + if (_query == k.name) { + return k; + } + } + throw UtilsException("Unknown KEM algorithm!"); + } + + /// Returns all available [KemAlgorithm] as String list + static List getAvailableKemAlgorithms() { + List _res = []; + for (KemAlgorithm k in KemAlgorithm.values) { + _res.add(k.name); + } + return _res; + } + + /// Returns [CipherParameters] from string. + /// + /// For example, `CBC/PKCS5` gives a CipherParameters with + /// CBC mode and PKCS5 as padding. + static CipherParameters getCipherParameters(String parameters) { + List _query = parameters.toLowerCase().split("/"); + BlockCipherMode _mode; + Padding _padding; + for (BlockCipherMode b in BlockCipherMode.values) { + if (_query[0] == b.name) { + _mode = b; + } + } + for (Padding p in Padding.values) { + if (_query[1] == p.name) { + _padding = p; + } + } + if (_mode == null || _padding == null) { + throw UtilsException("Unknown parameters!"); + } else { + return CipherParameters(_mode, _padding); + } + } +}