1 module dcrypto.properties;
2 
3 import dcrypto.evp;
4 import std.string;
5 import std.typecons;
6 import std.base64;
7 
8 version (Have_vibe_d) {
9 	import vibe.data.json;
10 }
11 
12 string encryptProperty(const string value, const string secret) {
13 	auto key = keyFromSecret(secret);
14 	auto encrypter = new EVPEncryptor(key);
15 	
16 	auto joined = key.salt ~ representation(encrypter.encrypt(value));
17 	
18 	return Base64.encode(joined);
19 }
20 
21 string decryptProperty(const string value, const string secret) {
22 	auto data = cast(string)Base64.decode(value);
23 	assert(data.length > 8, "The value for the encrypted property is not long enough");
24 	auto key = keyFromSecret(secret, data[0..8]);
25 	auto decrypter = new EVPDecryptor(key);
26 	
27 	return decrypter.decrypt(data[8..$]);
28 }
29 
30 string encryptedProperty(string name, string secret) {
31 	string code;
32 	
33 	code ~= format("string %s_encrypted_;", name);
34 	
35 	version (Have_vibe_d) {
36 		auto ignore = "@ignore ";
37 	} else {
38 		auto ignore = "";
39 	}
40 	code ~= format("%s@property string %s() { ", ignore, name);
41 	code ~= format("return decryptProperty(%s_encrypted_, \"%s\");", name, secret);
42 	code ~= "}";
43 	
44 	code ~= format("@property void %s(string value) { ", name);
45 	code ~= format("%s_encrypted_ = encryptProperty(value, \"%s\");", name, secret);
46 	code ~= "}";
47 	
48 	return code;
49 }
50 
51 unittest {
52 	struct User {
53 		string username;
54 		mixin (encryptedProperty("password", "ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
55 		mixin (encryptedProperty("creditCard", "ZYXWVUTSRXPONMLKJIHGFEDCBA"));
56 	}
57 	
58 	User user;
59 	user.username = "David";
60 	user.password = "SuperSecretPassword";
61 	user.creditCard = "1234 5258 4566 9789";
62 	
63 	auto output = Base64.encode(representation(user.password_encrypted_));
64 
65 	assert(user.password_encrypted_ != "SuperSecretPassword");
66 	assert(user.password == "SuperSecretPassword");
67 	assert(user.creditCard == "1234 5258 4566 9789");
68 }