1 module dcrypt.crypto.digests.generaldigest;
2 
3 public import dcrypt.crypto.digest;
4 
5 /**
6  * base implementation of MD4 family style digest as outlined in
7  * "Handbook of Applied Cryptography", pages 344 - 347.
8  */
9 @safe
10 package class GeneralDigest : Digest
11 {
12 	alias put update;
13 
14 public:
15 
16 	override void put(in ubyte[] input...) nothrow @nogc
17 	{
18 		uint inOff = 0;
19 		size_t len = input.length;
20 		//
21 		// fill the current word
22 		//
23 		while ((xBufOff != 0) && (len > 0))
24 		{
25 			putSingleByte(input[inOff]);
26 
27 			inOff++;
28 			len--;
29 		}
30 
31 		//
32 		// process whole words.
33 		//
34 		while (len > xBuf.length)
35 		{
36 			processWord(input[inOff .. $]);
37 
38 			inOff += xBuf.length;
39 			len -= xBuf.length;
40 			byteCount += xBuf.length;
41 		}
42 
43 		//
44 		// load in the remainder.
45 		//
46 		while (len > 0)
47 		{
48 			putSingleByte(input[inOff]);
49 
50 			inOff++;
51 			len--;
52 		}
53 	}
54 
55 	protected void finish() nothrow @nogc
56 	{
57 		ulong    bitLength = (byteCount << 3);
58 
59 		//
60 		// add the pad bytes.
61 		//
62 		put(128);
63 
64 		while (xBufOff != 0)
65 		{
66 			put(0);
67 		}
68 
69 		processLength(bitLength);
70 
71 		processBlock();
72 	}
73 
74 	override void start() nothrow @nogc
75 	{
76 		byteCount = 0;
77 
78 		xBufOff = 0;
79 		xBuf[] = 0;
80 	}
81 	
82 	override uint blockSize() pure nothrow @nogc {
83 		return 64;
84 	}
85 	
86 	//    abstract string getAlgorithmName() pure nothrow;
87 	//    abstract uint getDigestSize() pure nothrow;
88 	//    abstract uint doFinal(ubyte[] output);
89 
90 	override uint getByteLength() pure nothrow @nogc
91 	{
92 		return BYTE_LENGTH;
93 	}
94 	
95 	@property
96 	public override GeneralDigest dup() nothrow {
97 		GeneralDigest clone = dupImpl();
98 		clone.xBuf = xBuf;
99 		clone.xBufOff = xBufOff;
100 		clone.byteCount = byteCount;
101 		return clone;
102 	}
103 	
104 	/// create an independant clone. used by dup()
105 	protected abstract GeneralDigest dupImpl() nothrow;
106 	
107 	protected abstract nothrow @nogc {
108 		void processWord(in ubyte[] input);
109 		void processLength(ulong bitLength);
110 		void processBlock();
111 	}
112 
113 	protected void putSingleByte(ubyte input) nothrow @nogc
114 	{
115 		xBuf[xBufOff++] = input;
116 		
117 		if (xBufOff == xBuf.length)
118 		{
119 			processWord(xBuf);
120 			xBufOff = 0;
121 		}
122 		
123 		byteCount++;
124 	}
125 	
126 	private {
127 		enum BYTE_LENGTH = 64;
128 		ubyte[4]  xBuf;
129 		uint     xBufOff = 0;
130 
131 		size_t    byteCount;
132 	}
133 	
134 }