Add async "constructors" for key generation
This commit is contained in:
parent
acc9261a66
commit
e4fa93a775
@ -9,6 +9,8 @@ import 'platform.dart';
|
|||||||
|
|
||||||
import 'exceptions.dart';
|
import 'exceptions.dart';
|
||||||
import 'keyspec.dart';
|
import 'keyspec.dart';
|
||||||
|
import 'cipher.dart';
|
||||||
|
import 'utils.dart';
|
||||||
|
|
||||||
/// This is the base class of all key types.
|
/// This is the base class of all key types.
|
||||||
abstract class Key {
|
abstract class Key {
|
||||||
@ -33,21 +35,21 @@ abstract class Key {
|
|||||||
/// This represents a secret key, usefull in
|
/// This represents a secret key, usefull in
|
||||||
/// algorithms like AES or BlowFish.
|
/// algorithms like AES or BlowFish.
|
||||||
class SecretKey extends Key {
|
class SecretKey extends Key {
|
||||||
List<String> _supportedAlgorithms = ["AES", "Blowfish"];
|
|
||||||
|
|
||||||
/// Creates a key from raw byte array
|
/// Creates a key from raw byte array
|
||||||
SecretKey.fromBytes(Uint8List bytes) : super(bytes: bytes);
|
SecretKey.fromBytes(Uint8List bytes,
|
||||||
|
{CipherAlgorithm algorithm: CipherAlgorithm.None})
|
||||||
|
: super(bytes: bytes, algorithm: algorithm.name);
|
||||||
|
|
||||||
/// Creates a key from a specific size.
|
/// Creates a key from a specific size.
|
||||||
SecretKey.generate(String algorithm, int size) {
|
static Future<SecretKey> generate(int size, CipherAlgorithm algorithm) async {
|
||||||
if (!_supportedAlgorithms.contains(algorithm)) {
|
if (algorithm == null) {
|
||||||
throw KeyException(algorithm + " not supported!");
|
throw KeyException("Algorithm can't be null");
|
||||||
} else if (algorithm == "AES") {
|
} else if (algorithm == CipherAlgorithm.AES) {
|
||||||
List<int> supportedSizes = [128, 192, 256];
|
List<int> _supportedSizes = [128, 192, 256];
|
||||||
if (!supportedSizes.contains(size)) {
|
if (!_supportedSizes.contains(size)) {
|
||||||
throw KeyException("AES must be 128, 192 or 256 bits long.");
|
throw KeyException("AES must be 128, 192 or 256 bits long.");
|
||||||
}
|
}
|
||||||
} else if (algorithm == "Blowfish") {
|
} else if (algorithm == CipherAlgorithm.BlowFish) {
|
||||||
List<int> supportedSizes =
|
List<int> supportedSizes =
|
||||||
List<int>.generate(52, (int index) => (index + 4) * 8);
|
List<int>.generate(52, (int index) => (index + 4) * 8);
|
||||||
if (!supportedSizes.contains(size)) {
|
if (!supportedSizes.contains(size)) {
|
||||||
@ -55,15 +57,12 @@ class SecretKey extends Key {
|
|||||||
"Blowfish must be between 4 and 56 bytes (32 and 448 bits) long.");
|
"Blowfish must be between 4 and 56 bytes (32 and 448 bits) long.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_generate(algorithm, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _generate(String algo, int size) async {
|
|
||||||
try {
|
try {
|
||||||
_bytes = await Platform().keygen(size);
|
Uint8List _key = await Platform().keygen(size);
|
||||||
_algo = algo;
|
log("Generated SecretKey size: ${_key.length * 8} bits (${_key.length} bytes)",
|
||||||
log("Generated SecretKey size: ${_bytes.length * 8} bits (${_bytes.length} bytes)",
|
|
||||||
name: "NativeCrypto");
|
name: "NativeCrypto");
|
||||||
|
return SecretKey.fromBytes(_key, algorithm: algorithm);
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
log(e.message, name: "NativeCrypto");
|
log(e.message, name: "NativeCrypto");
|
||||||
throw KeyException(e);
|
throw KeyException(e);
|
||||||
|
@ -12,15 +12,29 @@ import '../utils.dart';
|
|||||||
/// Defines all available key sizes.
|
/// Defines all available key sizes.
|
||||||
enum AESKeySize { bits128, bits192, bits256 }
|
enum AESKeySize { bits128, bits192, bits256 }
|
||||||
|
|
||||||
|
extension AESKeySizeExtension on AESKeySize {
|
||||||
|
int get length {
|
||||||
|
int l;
|
||||||
|
switch (this) {
|
||||||
|
case AESKeySize.bits128:
|
||||||
|
l = 128;
|
||||||
|
break;
|
||||||
|
case AESKeySize.bits192:
|
||||||
|
l = 192;
|
||||||
|
break;
|
||||||
|
case AESKeySize.bits256:
|
||||||
|
l = 256;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class AESCipher implements Cipher {
|
class AESCipher implements Cipher {
|
||||||
SecretKey _sk;
|
SecretKey _sk;
|
||||||
CipherParameters _params;
|
CipherParameters _params;
|
||||||
bool _isInit;
|
bool _isInit;
|
||||||
|
|
||||||
List<CipherParameters> _supportedCipherParams = [
|
|
||||||
CipherParameters(BlockCipherMode.CBC, Padding.PKCS5),
|
|
||||||
];
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
CipherAlgorithm get algorithm => CipherAlgorithm.AES;
|
CipherAlgorithm get algorithm => CipherAlgorithm.AES;
|
||||||
|
|
||||||
@ -33,34 +47,31 @@ class AESCipher implements Cipher {
|
|||||||
@override
|
@override
|
||||||
bool get isInitialized => _isInit;
|
bool get isInitialized => _isInit;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<CipherParameters> get supportedParameters => [
|
||||||
|
CipherParameters(BlockCipherMode.CBC, PlainTextPadding.PKCS5),
|
||||||
|
];
|
||||||
|
|
||||||
/// Creates an AES cipher with specified secretKey and mode/padding
|
/// Creates an AES cipher with specified secretKey and mode/padding
|
||||||
AESCipher(SecretKey secretKey, CipherParameters parameters) {
|
AESCipher(SecretKey secretKey, CipherParameters parameters) {
|
||||||
if (secretKey.algorithm != "AES") {
|
if (secretKey.algorithm != CipherAlgorithm.AES.name) {
|
||||||
throw CipherInitException("Invalid key type: " + secretKey.algorithm);
|
List<int> _supportedSizes = [128, 192, 256];
|
||||||
} else if (!_supportedCipherParams.contains(parameters)) {
|
if (!_supportedSizes.contains(secretKey.encoded.length)) {
|
||||||
|
throw CipherInitException("Invalid key length!");
|
||||||
|
}
|
||||||
|
} else if (!supportedParameters.contains(parameters)) {
|
||||||
throw CipherInitException("Invalid cipher parameters.");
|
throw CipherInitException("Invalid cipher parameters.");
|
||||||
}
|
}
|
||||||
|
_sk = secretKey;
|
||||||
_params = parameters;
|
_params = parameters;
|
||||||
_isInit = true;
|
_isInit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a secret key of specified size, then creates an AES cipher.
|
/// Generates a secret key of specified size, then creates an AES cipher.
|
||||||
AESCipher.generate(AESKeySize size, CipherParameters parameters) {
|
static Future<AESCipher> generate(
|
||||||
Map<AESKeySize, int> _supportedSizes = {
|
AESKeySize size, CipherParameters parameters) async {
|
||||||
AESKeySize.bits128: 128,
|
SecretKey _sk = await SecretKey.generate(size.length, CipherAlgorithm.AES);
|
||||||
AESKeySize.bits192: 192,
|
return AESCipher(_sk, parameters);
|
||||||
AESKeySize.bits256: 256
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!_supportedCipherParams.contains(parameters)) {
|
|
||||||
throw CipherInitException("Invalid cipher parameters.");
|
|
||||||
} else if (!_supportedSizes.containsKey(size)) {
|
|
||||||
throw CipherInitException("Invalid key size.");
|
|
||||||
}
|
|
||||||
|
|
||||||
_sk = SecretKey.generate("AES", _supportedSizes[size]);
|
|
||||||
_params = parameters;
|
|
||||||
_isInit = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user