1 module dcrypto.key;
2 
3 import std.random;
4 import std..string;
5 
6 import deimos.openssl.evp;
7 
8 import dcrypto.dcrypto;
9 
10 /// Basic struct for for storing a key. Includes a key, an iv and a salt.
11 struct Key {
12 	ubyte[] key, iv, salt;
13 
14 	/// Allocates memory for the requested key lengths. By default they are set to the maximum values per the openssl library.
15 	void setSize(int keyLength = EVP_MAX_KEY_LENGTH, int ivLength = EVP_MAX_IV_LENGTH) {
16 		key = new ubyte[](keyLength);
17 		iv = new ubyte[](ivLength);
18 	}
19 
20 	/// Creates a random salt of the specified size.
21 	ref Key randomizeSalt(size_t size = 8) {
22 		salt = new ubyte[](size);
23 		fillRandom!ubyte(salt);
24 		return this;
25 	}
26 
27 	/// Creates a random key and iv of the specified size
28 	ref Key randomize(int keyLength = EVP_MAX_KEY_LENGTH, int ivLength = EVP_MAX_IV_LENGTH) {
29 		setSize(keyLength, ivLength);
30 		fillRandom!ubyte(key);
31 		fillRandom!ubyte(iv);
32 		return this;
33 	}
34 	
35 }
36 
37 /// Build and return a key based on secret data with a random salt generated
38 Key keyFromSecret(string data, int rounds = 200, int keyLength = EVP_MAX_KEY_LENGTH, int ivLength = EVP_MAX_IV_LENGTH) {
39 	Key returnKey;
40 
41 	returnKey.randomizeSalt();
42 	returnKey.setSize(keyLength, ivLength);
43 
44 	auto d = representation(data);
45 	EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha256(), returnKey.salt.ptr, d.ptr, returnKey.key.sizeof, rounds, returnKey.key.ptr, returnKey.iv.ptr);
46 
47 	return returnKey;
48 }
49 
50 /// Build and return a key based on secret data using the specified salt
51 Key keyFromSecret(string data, string salt, int rounds = 200, int keyLength = EVP_MAX_KEY_LENGTH, int ivLength = EVP_MAX_IV_LENGTH) {
52 	Key returnKey;
53 
54 	returnKey.salt = representation(salt).dup;
55 	returnKey.setSize(keyLength, ivLength);
56 
57 	auto d = representation(data);
58 	EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha256(), returnKey.salt.ptr, d.ptr, returnKey.key.sizeof, rounds, returnKey.key.ptr, returnKey.iv.ptr);
59 	
60 	return returnKey;
61 }