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 }