1 /*******************************************************************************
2 
3         This module implements the SHA-256 Algorithm described by Secure
4         Hash Standard, FIPS PUB 180-2
5 
6         Copyright:
7             Copyright (c) 2006 Tango contributors.
8             Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH.
9             All rights reserved.
10 
11         License:
12             Tango Dual License: 3-Clause BSD License / Academic Free License v3.0.
13             See LICENSE_TANGO.txt for details.
14 
15         Version: Initial release: Feb 2006
16 
17         Authors: Regan Heath, Oskar Linde
18 
19 *******************************************************************************/
20 
21 module ocean.util.digest.Sha256;
22 
23 import ocean.meta.types.Qualifiers;
24 
25 import ocean.core.ByteSwap;
26 
27 public  import ocean.util.digest.Digest;
28 
29 import ocean.util.digest.MerkleDamgard;
30 
31 version (unittest) import ocean.core.Test;
32 
33 /*******************************************************************************
34 
35 *******************************************************************************/
36 
37 final class Sha256 : MerkleDamgard
38 {
39         private uint[8]         context;
40         private static immutable uint      padChar = 0x80;
41 
42         /***********************************************************************
43 
44                 Construct an Sha256
45 
46         ***********************************************************************/
47 
48         this() { }
49 
50         /***********************************************************************
51 
52                 Initialize the cipher
53 
54                 Remarks:
55                 Returns the cipher state to it's initial value
56 
57         ***********************************************************************/
58 
59         protected override void reset()
60         {
61                 super.reset();
62                 context[] = initial[];
63         }
64 
65         /***********************************************************************
66 
67                 Obtain the digest
68 
69                 Remarks:
70                 Returns a digest of the current cipher state, this may be the
71                 final digest, or a digest of the state between calls to update()
72 
73         ***********************************************************************/
74 
75         protected override void createDigest (ubyte[] buf)
76         {
77                 version (LittleEndian)
78                          ByteSwap.swap32 (context.ptr, context.length * uint.sizeof);
79 
80                 buf[] = cast(ubyte[]) context;
81         }
82 
83         /***********************************************************************
84 
85                 The digest size of Sha-256 is 32 bytes
86 
87         ***********************************************************************/
88 
89         override uint digestSize() { return 32; }
90 
91         /***********************************************************************
92 
93                 Cipher block size
94 
95                 Returns:
96                 the block size
97 
98                 Remarks:
99                 Specifies the size (in bytes) of the block of data to pass to
100                 each call to transform(). For SHA256 the blockSize is 64.
101 
102         ***********************************************************************/
103 
104         protected override uint blockSize() { return 64; }
105 
106         /***********************************************************************
107 
108                 Length padding size
109 
110                 Returns:
111                 the length padding size
112 
113                 Remarks:
114                 Specifies the size (in bytes) of the padding which uses the
115                 length of the data which has been ciphered, this padding is
116                 carried out by the padLength method. For SHA256 the addSize is 8.
117 
118         ***********************************************************************/
119 
120         protected override uint addSize()   { return 8;  }
121 
122         /***********************************************************************
123 
124                 Pads the cipher data
125 
126                 Params:
127                 data = a slice of the cipher buffer to fill with padding
128 
129                 Remarks:
130                 Fills the passed buffer slice with the appropriate padding for
131                 the final call to transform(). This padding will fill the cipher
132                 buffer up to blockSize()-addSize().
133 
134         ***********************************************************************/
135 
136         protected override void padMessage(ubyte[] data)
137         {
138                 data[0] = padChar;
139                 data[1..$] = 0;
140         }
141 
142         /***********************************************************************
143 
144                 Performs the length padding
145 
146                 Params:
147                 data   = the slice of the cipher buffer to fill with padding
148                 length = the length of the data which has been ciphered
149 
150                 Remarks:
151                 Fills the passed buffer slice with addSize() bytes of padding
152                 based on the length in bytes of the input data which has been
153                 ciphered.
154 
155         ***********************************************************************/
156 
157         protected override void padLength(ubyte[] data, size_t length)
158         {
159                 length <<= 3;
160                 for(ptrdiff_t j = data.length-1; j >= 0; j--)
161                         data[$-j-1] = cast(ubyte) (length >> j*8);
162         }
163 
164         /***********************************************************************
165 
166                 Performs the cipher on a block of data
167 
168                 Params:
169                 input = the block of data to cipher
170 
171                 Remarks:
172                 The actual cipher algorithm is carried out by this method on
173                 the passed block of data. This method is called for every
174                 blockSize() bytes of input data and once more with the remaining
175                 data padded to blockSize().
176 
177         ***********************************************************************/
178 
179         protected override void transform(ubyte[] input)
180         {
181                 uint[64] W;
182                 uint a,b,c,d,e,f,g,h;
183                 uint j,t1,t2;
184 
185                 a = context[0];
186                 b = context[1];
187                 c = context[2];
188                 d = context[3];
189                 e = context[4];
190                 f = context[5];
191                 g = context[6];
192                 h = context[7];
193 
194                 bigEndian32(input,W[0..16]);
195                 for(j = 16; j < 64; j++) {
196                         W[j] = mix1(W[j-2]) + W[j-7] + mix0(W[j-15]) + W[j-16];
197                 }
198 
199                 for(j = 0; j < 64; j++) {
200                         t1 = h + sum1(e) + Ch(e,f,g) + K[j] + W[j];
201                         t2 = sum0(a) + Maj(a,b,c);
202                         h = g;
203                         g = f;
204                         f = e;
205                         e = d + t1;
206                         d = c;
207                         c = b;
208                         b = a;
209                         a = t1 + t2;
210                 }
211 
212                 context[0] += a;
213                 context[1] += b;
214                 context[2] += c;
215                 context[3] += d;
216                 context[4] += e;
217                 context[5] += f;
218                 context[6] += g;
219                 context[7] += h;
220         }
221 
222         /***********************************************************************
223 
224         ***********************************************************************/
225 
226         private static uint Ch(uint x, uint y, uint z)
227         {
228                 return (x&y)^(~x&z);
229         }
230 
231         /***********************************************************************
232 
233         ***********************************************************************/
234 
235         private static uint Maj(uint x, uint y, uint z)
236         {
237                 return (x&y)^(x&z)^(y&z);
238         }
239 
240         /***********************************************************************
241 
242         ***********************************************************************/
243 
244         private static uint sum0(uint x)
245         {
246                 return rotateRight(x,2)^rotateRight(x,13)^rotateRight(x,22);
247         }
248 
249         /***********************************************************************
250 
251         ***********************************************************************/
252 
253         private static uint sum1(uint x)
254         {
255                 return rotateRight(x,6)^rotateRight(x,11)^rotateRight(x,25);
256         }
257 
258         /***********************************************************************
259 
260         ***********************************************************************/
261 
262         private static uint mix0(uint x)
263         {
264                 return rotateRight(x,7)^rotateRight(x,18)^shiftRight(x,3);
265         }
266 
267         /***********************************************************************
268 
269         ***********************************************************************/
270 
271         private static uint mix1(uint x)
272         {
273                 return rotateRight(x,17)^rotateRight(x,19)^shiftRight(x,10);
274         }
275 
276         /***********************************************************************
277 
278         ***********************************************************************/
279 
280         private static uint rotateRight(uint x, uint n)
281         {
282                 return (x >> n) | (x << (32-n));
283         }
284 
285         /***********************************************************************
286 
287         ***********************************************************************/
288 
289         private static uint shiftRight(uint x, uint n)
290         {
291                 return x >> n;
292         }
293 }
294 
295 
296 /*******************************************************************************
297 
298 *******************************************************************************/
299 
300 private static uint[] K =
301 [
302         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
303         0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
304         0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
305         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
306         0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
307         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
308         0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
309         0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
310 ];
311 
312 /*******************************************************************************
313 
314 *******************************************************************************/
315 
316 private static const(uint[8]) initial =
317 [
318         0x6a09e667,
319         0xbb67ae85,
320         0x3c6ef372,
321         0xa54ff53a,
322         0x510e527f,
323         0x9b05688c,
324         0x1f83d9ab,
325         0x5be0cd19
326 ];
327 
328 /*******************************************************************************
329 
330 *******************************************************************************/
331 
332 unittest
333 {
334     static istring[] strings =
335     [
336             "abc",
337             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
338     ];
339 
340     static istring[] results =
341     [
342             "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
343             "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
344     ];
345 
346     Sha256 h = new Sha256();
347 
348     foreach (i, s; strings)
349     {
350         h.update(s);
351         char[] d = h.hexDigest();
352         test(d == results[i],"Cipher:("~s~")("~d~")!=("~results[i]~")");
353     }
354 }