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 }