1 module dcrypto.evp;
2 
3 public import dcrypto.key;
4 import dcrypto.dcrypto;
5 
6 import deimos.openssl.evp;
7 
8 import std.string;
9 
10 
11 class EVPEncryptDecryptBase {
12 public
13 	this() {
14 		EVP_CIPHER_CTX_init(&_context);
15 	}
16 	
17 	this(const ref Key key) {
18 		this();
19 		init(key);
20 	}
21 
22 protected:
23 	EVP_CIPHER_CTX _context;
24 
25 	abstract void init(const ref Key key, const EVP_CIPHER *algorithm);
26 	public void init(const ref Key key) {
27 		init(key, EVP_aes_256_cbc());
28 	}
29 }
30 
31 class EVPEncryptor : EVPEncryptDecryptBase, Encryptor {
32 	this() { super(); }
33 	this(const ref Key key) { super(key); }
34 	
35 	override string encrypt(const string input) {
36 		auto source = representation(input);
37 		auto buffer = new ubyte[](source.length + EVP_MAX_BLOCK_LENGTH);
38 		int length, lengthFinal;
39 		
40 		EVP_EncryptInit(&_context, null, null, null);
41 		EVP_EncryptUpdate(&_context, buffer.ptr, &length, source.ptr, cast(int)source.length);
42 		EVP_EncryptFinal_ex(&_context, buffer.ptr + length, &lengthFinal);
43 		
44 		return cast(string)buffer[0..length + lengthFinal];
45 	}
46 
47 protected:
48 	override void init(const ref Key key, const EVP_CIPHER *algorithm) {
49 		EVP_EncryptInit(&_context, algorithm, key.key.ptr, key.iv.ptr);
50 	}
51 }
52 
53 class EVPDecryptor : EVPEncryptDecryptBase, Decryptor {
54 	this() { super(); }
55 	this(const ref Key key) { super(key); }
56 	
57 	override string decrypt(const string input) {
58 		auto source = representation(input);
59 		auto buffer = new ubyte[](source.length + EVP_MAX_BLOCK_LENGTH);
60 		int length, lengthFinal;
61 		
62 		EVP_DecryptInit(&_context, null, null, null);
63 		EVP_DecryptUpdate(&_context, buffer.ptr, &length, source.ptr, cast(int)source.length);
64 		EVP_DecryptFinal_ex(&_context, buffer.ptr + length, &lengthFinal);
65 		
66 		return cast(string)buffer[0..length + lengthFinal];
67 	}
68 protected:
69 	override void init(const ref Key key, const EVP_CIPHER *algorithm) {
70 		EVP_DecryptInit(&_context, algorithm, key.key.ptr, key.iv.ptr);
71 	}
72 }
73 
74 unittest {
75 	auto key = keyFromSecret("ZYXWVUTSRQPONMLKJIHGFEDCBA", "SALT");
76 	auto encryptor = new EVPEncryptor(key);
77 	auto decryptor = new EVPDecryptor(key);
78 
79 	auto encrypted = encryptor.encrypt("This is a decrypted string");
80 	auto encrypted2 = encryptor.encrypt("This is a second decrypted string");
81 
82 	assert(decryptor.decrypt(encrypted2) == "This is a second decrypted string");
83 	assert(decryptor.decrypt(encrypted) == "This is a decrypted string");
84 	assert(decryptor.decrypt(encrypted2) == "This is a second decrypted string");
85 
86 	auto key2 = keyFromSecret("ZYXWVUTSRQPONMLKJIHGFEDCBA");
87 	auto decryptor2 = new EVPDecryptor(key2);
88 	assert(decryptor2.decrypt(encrypted2) != "This is a second decrypted string");
89 }