Add key size support

This commit is contained in:
Hugo Pointcheval 2020-04-15 21:34:58 +02:00
parent e58132124d
commit 2b020f4fe3

View File

@ -2,19 +2,26 @@
// Author: Hugo Pointcheval // Author: Hugo Pointcheval
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:native_crypto/native_crypto.dart'; import 'package:native_crypto/src/native_crypto.dart';
import 'package:native_crypto/src/exceptions.dart'; import 'package:native_crypto/src/exceptions.dart';
/// Defines all available key sizes.
enum KeySize { bits128, bits192, bits256 } enum KeySize { bits128, bits192, bits256 }
/// Defines all available ciphers.
enum Cipher { AES } enum Cipher { AES }
/// AES Helper /// AES Helper
/// ///
/// You can generate AES keys, encrypt and decrypt data. /// You can generate AES keys, encrypt and decrypt data.
class AES { class AES {
/// This key is used for encryption and decryption.
Uint8List key; Uint8List key;
/// Check if the AES object is intialized with a valid key before perform any operation.
bool isInitialized = false; bool isInitialized = false;
/// Defines the size of the generated or passed key.
KeySize keySize; KeySize keySize;
/// You can pass a key in constructor. /// You can pass a key in constructor.
@ -28,6 +35,7 @@ class AES {
} }
} }
/// [Private]
/// Tests if the key is valid. /// Tests if the key is valid.
/// ///
/// The key must be 128, 192 or 256 bits long. /// The key must be 128, 192 or 256 bits long.
@ -53,13 +61,31 @@ class AES {
} }
/// Generate an AES key. /// Generate an AES key.
init(KeySize keySize) async { ///
/// You can specify a `keySize`. Default is 256 bits.
/// Return `null` if the key is already set.
init({KeySize keySize}) async {
if (this.key != null) return null; if (this.key != null) return null;
if (keySize != KeySize.bits256) int size;
throw NotImplementedException('This key size is not implemented yet.');
this.key = await NativeCrypto().symKeygen(); switch (keySize) {
case KeySize.bits128:
size = 128;
break;
case KeySize.bits192:
size = 192;
break;
case KeySize.bits256:
size = 256;
break;
default:
// Default size = 256 bits
size = 256;
break;
}
this.key = await NativeCrypto().symKeygen(size);
try { try {
bool isValidKey = _testKey(); bool isValidKey = _testKey();
this.isInitialized = isValidKey; this.isInitialized = isValidKey;
@ -69,11 +95,13 @@ class AES {
} }
} }
/// Encrypt data /// Encrypts data.
/// ///
/// Returns an `Encrypted` object. /// Takes `Uint8List` data as parameter.
/// And returns an `Encrypted` object.
Future<Encrypted> encrypt(Uint8List data) async { Future<Encrypted> encrypt(Uint8List data) async {
if (!this.isInitialized) throw EncryptionException('Instance not initialized.'); if (!this.isInitialized)
throw EncryptionException('Instance not initialized.');
List<Uint8List> encryptedPayload = List<Uint8List> encryptedPayload =
await NativeCrypto().symEncrypt(data, this.key); await NativeCrypto().symEncrypt(data, this.key);
Encrypted encrypted = Encrypted.fromList(Cipher.AES, encryptedPayload); Encrypted encrypted = Encrypted.fromList(Cipher.AES, encryptedPayload);
@ -81,8 +109,13 @@ class AES {
return encrypted; return encrypted;
} }
/// Decrypts data.
///
/// Takes `Encrypted` object as parameter.
/// And returns plain text data as `Uint8List`.
Future<Uint8List> decrypt(Encrypted encrypted) async { Future<Uint8List> decrypt(Encrypted encrypted) async {
if (!this.isInitialized) throw DecryptionException('Instance not initialized.'); if (!this.isInitialized)
throw DecryptionException('Instance not initialized.');
Uint8List decryptedPayload = Uint8List decryptedPayload =
await NativeCrypto().symDecrypt(encrypted.toList(), this.key); await NativeCrypto().symDecrypt(encrypted.toList(), this.key);
return decryptedPayload; return decryptedPayload;
@ -92,21 +125,36 @@ class AES {
/// Contains data of an encrypted payload. /// Contains data of an encrypted payload.
/// More practical than a list. /// More practical than a list.
class Encrypted { class Encrypted {
/// Contains encryption algorithm.
Cipher cipher; Cipher cipher;
/// Contains encrypted bytes.
Uint8List cipherText; Uint8List cipherText;
/// Contains IV used for encryption.
///
/// Needed for decryption.
Uint8List iv; Uint8List iv;
/// Contains MAC.
///
/// Used in decryption to authenticate the data.
Uint8List mac; Uint8List mac;
Encrypted(); /// Creates an encrypted from payload `List<Uint8List>`.
Encrypted.fromList(this.cipher, List<Uint8List> encryptedPayload) { Encrypted.fromList(this.cipher, List<Uint8List> encryptedPayload) {
this.mac = encryptedPayload[0].sublist(0, 32); this.mac = encryptedPayload[0].sublist(0, 32);
this.cipherText = encryptedPayload[0].sublist(32, encryptedPayload[0].length); this.cipherText =
encryptedPayload[0].sublist(32, encryptedPayload[0].length);
this.iv = encryptedPayload[1]; this.iv = encryptedPayload[1];
} }
/// Returns a payload `List<Uint8List>` from this encrypted.
List<Uint8List> toList() { List<Uint8List> toList() {
List<Uint8List> encryptedPayload = [Uint8List.fromList(this.mac + this.cipherText), this.iv]; List<Uint8List> encryptedPayload = [
Uint8List.fromList(this.mac + this.cipherText),
this.iv
];
return encryptedPayload; return encryptedPayload;
} }
} }