1 /// Digests and ingests for various cryptography algorithms. 2 module tern.digest; 3 4 import tern.traits; 5 import tern.serialization; 6 import tern.meta; 7 import std.meta; 8 9 /// Attribute for marking a class as a digester, must implement `encrypt` or `hash ` 10 public enum digester; 11 12 /// True if `T` is a digester of any kind. 13 public alias isDigest(T) = Alias!(seqContains!(digester, __traits(getAttributes, T))); 14 /// True if `T` is an encrypting digester. 15 public alias isEncryptingDigest(T) = Alias!(isDigest!T && hasStaticMember!(T, "encrypt")); 16 /// True if `T` is an hashing digester. 17 public alias isHashingDigest(T) = Alias!(isDigest!T && hasStaticMember!(T, "hash")); 18 19 /* public class Digest(T, IV...) 20 if (isDigest!T) 21 { 22 protected: 23 final: 24 ubyte[] data; 25 IV iv; 26 27 public: 28 this(IV iv) 29 { 30 this.iv = iv; 31 } 32 33 auto digest(T)(size_t count = 1) 34 { 35 T[] ret; 36 foreach (i; 0..count) 37 ret ~= deserialize!T(serialize!true(digest(T.sizeof * count))); 38 return ret; 39 } 40 41 auto digest(size_t size) 42 { 43 scope (exit) data = data[size..$]; 44 static if (isEncryptingDigest!T) 45 return T.encrypt(*cast(ubyte[]*)data[0..size], iv); 46 else static if (isHashingDigest!T) 47 return T.hash(data[0..size], iv); 48 } 49 50 auto digest(ARGS...)(size_t size, ARGS args) 51 { 52 auto data = this.data[0..size]; 53 static if (isEncryptingDigest!T) 54 return T.encrypt(data, args); 55 else static if (isHashingDigest!T) 56 return T.hash(*cast(ubyte[]*)data[0..size], args); 57 } 58 59 auto ingest(T)(size_t count = 1) 60 { 61 T[] ret; 62 foreach (i; 0..count) 63 ret ~= deserialize!T(serialize!true(ingest(T.sizeof * count))); 64 return ret; 65 } 66 67 auto ingest(size_t size) 68 { 69 auto data = this.data[0..size]; 70 scope (exit) data = data[size..$]; 71 static if (isEncryptingDigest!T) 72 return T.decrypt(*cast(ubyte[]*)data[0..size], iv); 73 else static if (isHashingDigest!T) 74 return (serialize!true(T.hash(data[0..size], iv))).toHexString(); 75 } 76 77 auto ingest(ARGS...)(size_t size, ARGS args) 78 { 79 static if (isEncryptingDigest!T) 80 return T.decrypt(*cast(ubyte[]*)data[0..size], args); 81 else static if (isHashingDigest!T) 82 return (serialize!true(T.hash(data[0..size], args))).toHexString(); 83 } 84 85 void devour(ubyte[] data) 86 { 87 this.data ~= data; 88 } 89 90 void drop(size_t size) 91 { 92 data = data[size..$]; 93 } 94 } */ 95 96 public: 97 static: 98 /** 99 * Digests arguments by the given provider `T`. 100 * `T` must either have a `encrypt` or `hash` function present. 101 * 102 * Remarks: 103 * - If `T` has a hash function present, the output will be the output of the hash function. 104 * - If `T` has an encrypt function present, the output will be the output of the encryption function. 105 */ 106 public auto digest(T, ARGS...)(ARGS args) 107 if (isEncryptingDigest!T) 108 { 109 return T.encrypt(args); 110 } 111 112 /** 113 * Ingests arguments by the given provider `T` 114 * `T` must either have a `decrypt` or `hash` function present. 115 * 116 * Remarks: 117 * - If `T` has a hash function present, the output will be the output of the hash function serialized as a string. 118 * - If `T` has a decrypt function present, the output will be the output of the decryption function. 119 */ 120 public auto ingest(T, ARGS...)(ARGS args) 121 if (isEncryptingDigest!T) 122 { 123 return T.decrypt(args); 124 } 125 126 /** 127 * Digests arguments by the given provider `T` 128 * `T` must either have a `encrypt` or `hash` function present. 129 * 130 * Remarks: 131 * - If `T` has a hash function present, the output will be the output of the hash function. 132 * - If `T` has an encrypt function present, the output will be the output of the encryption function. 133 */ 134 public auto digest(T, ARGS...)(ARGS args) 135 if (isHashingDigest!T) 136 { 137 return T.hash(args); 138 } 139 140 /** 141 * Ingests arguments by the given provider `T` 142 * `T` must either have a `decrypt` or `hash` function present. 143 * 144 * Remarks: 145 * - If `T` has a hash function present, the output will be the output of the hash function serialized as a string. 146 * - If `T` has a decrypt function present, the output will be the output of the decryption function. 147 */ 148 public auto ingest(T, ARGS...)(ARGS args) 149 if (isHashingDigest!T) 150 { 151 return (serialize!true(T.hash(args))).toHexString(); 152 } 153 154 string toHexString(ubyte[] data) 155 { 156 char hexDigit(ubyte value) 157 { 158 return value < 10 ? cast(char)('0' + value) : cast(char)('A' + (value - 10)); 159 } 160 161 string ret; 162 foreach (b; data) 163 { 164 ret ~= hexDigit(b >> 4); 165 ret ~= hexDigit(b & 0x0F); 166 } 167 return ret; 168 } 169