1 2 module dcrypt.crypto.macs.mac; 3 4 // TODO as output range 5 6 /// Test if T is a message authentication code (MAC). 7 template isMAC(T) 8 { 9 enum bool isMAC = 10 is(T == struct) && 11 is(typeof( 12 { 13 ubyte[] data; 14 T t = T.init; // can define 15 t.start(data); // set the mac key 16 t.reset(); // can reset the digest 17 18 t.put(cast(ubyte)0); // can add a single byte 19 t.put(data); // can add bytes 20 t.put(cast(ubyte)0, cast(ubyte)0); // has variadic put 21 22 uint len = t.doFinal(data); 23 auto macTag = t.finish(); 24 25 uint macSize = T.macSize; 26 string name = T.name; 27 28 })); 29 } 30 31 32 @safe 33 public abstract class Mac { 34 35 36 37 @safe @property 38 public abstract string name() pure nothrow; 39 40 /** 41 * Returns: the size, in bytes, of the MAC. 42 */ 43 @safe @property 44 public abstract uint macSize() pure nothrow; 45 46 /** 47 * update the MAC with a block of bytes. 48 * 49 * Params: 50 * input the ubyte slice containing the data. 51 */ 52 @safe 53 public abstract void put(in ubyte[] input...) nothrow; 54 55 /** 56 * close the MAC, producing the final MAC value. The doFinal 57 * call leaves the MAC reset(). */ 58 @safe 59 public abstract size_t doFinal(ubyte[] output) nothrow; 60 61 /** 62 * close the MAC, producing the final MAC value. The doFinal 63 * call leaves the MAC reset(). */ 64 @safe 65 public final ubyte[] doFinal() nothrow { 66 ubyte[] output = new ubyte[macSize]; 67 doFinal(output); 68 return output; 69 } 70 /** 71 * reset the digest back to it's initial state. 72 */ 73 @safe 74 public abstract void reset() nothrow ; 75 76 } 77 78 @safe 79 public class WrapperMac(T) if(isMAC!T) { 80 81 private T mac; 82 83 @safe @property 84 public string name() pure nothrow { 85 return mac.name; 86 } 87 88 /** 89 * Returns: the size, in bytes, of the MAC. 90 */ 91 @safe @property 92 public uint macSize() pure nothrow { 93 return mac.macSize; 94 } 95 96 @save 97 public void start(in ubyte[] key, in ubyte[] nonce = null); 98 99 /** 100 * update the MAC with a single byte. 101 * 102 * Params: 103 * input = the input byte to be entered. 104 */ 105 @safe 106 public void put(ubyte input) nothrow { 107 mac.put(input); 108 } 109 110 /** 111 * update the MAC with a block of bytes. 112 * 113 * Params: 114 * input the ubyte slice containing the data. 115 */ 116 @safe 117 public void put(in ubyte[] input) nothrow { 118 mac.put(input); 119 } 120 121 /** 122 * close the MAC, producing the final MAC value. The doFinal 123 * call leaves the MAC reset(). */ 124 @safe 125 public size_t doFinal(ubyte[] output) nothrow { 126 return mac.doFinal(output); 127 } 128 129 /** 130 * close the MAC, producing the final MAC value. The doFinal 131 * call leaves the MAC reset(). */ 132 @safe 133 public final ubyte[] doFinal() nothrow { 134 ubyte[] output = new ubyte[macSize]; 135 doFinal(output); 136 return output; 137 } 138 /** 139 * reset the digest back to it's initial state. 140 */ 141 @safe 142 public void reset() nothrow { 143 mac.reset(); 144 } 145 146 }