PageRenderTime 65ms CodeModel.GetById 17ms app.highlight 44ms RepoModel.GetById 1ms app.codeStats 0ms

/hashes/sha256.d

http://github.com/wilkie/djehuty
D | 153 lines | 91 code | 28 blank | 34 comment | 6 complexity | 25c3c70b52605662ee8c2805ebf840f1 MD5 | raw file
  1/*
  2 * sha256.d
  3 *
  4 * This module implements the SHA256 digest
  5 *
  6 * Author: Dave Wilkinson
  7 * Originated: January 19th, 2009
  8 *
  9 */
 10
 11module hashes.sha256;
 12
 13import core.stream;
 14import core.string;
 15import core.endian;
 16import core.definitions;
 17
 18import hashes.digest;
 19
 20// ---------------------------------
 21
 22class HashSHA256 {
 23static:
 24private:
 25
 26	uint k[64] = [
 27		0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
 28		0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
 29		0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
 30		0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
 31		0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
 32		0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
 33		0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
 34		0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
 35	];
 36
 37public:
 38
 39	Digest hash(ubyte[] message) {
 40		//Note 1: All variables are unsigned 32 bits and wrap modulo 2^32 when calculating
 41		//Note 2: All constants in this pseudo code are in big endian.
 42		//Within each word, the most significant bit is stored in the leftmost bit position
 43
 44		//Initialize variables:
 45		uint h0 = 0x6a09e667;
 46		uint h1 = 0xbb67ae85;
 47		uint h2 = 0x3c6ef372;
 48		uint h3 = 0xa54ff53a;
 49		uint h4 = 0x510e527f;
 50		uint h5 = 0x9b05688c;
 51		uint h6 = 0x1f83d9ab;
 52		uint h7 = 0x5be0cd19;
 53
 54		//Pre-processing
 55		//append the bit '1' to the message
 56		//append k bits '0', where k is the minimum number ? 0 such that the resulting message
 57		  //  length (in bits) is congruent to 448 (mod 512)
 58		//append length of message (before pre-processing), in bits, as 64-bit big-endian integer
 59
 60		int padBytes;
 61		uint bufferLen = message.length + 9;
 62
 63		// minimum increase of 9, after that the message must be padded
 64		if ((bufferLen % 64)) {
 65			padBytes = 64 - (cast(int)bufferLen % 64);
 66			if (padBytes < 0) {
 67				padBytes += 64;
 68			}
 69			bufferLen += padBytes;
 70		}
 71
 72		ubyte[] buffer = new ubyte[bufferLen];
 73		buffer[0..message.length] = message[0..$];
 74		buffer[message.length] = 0x80;
 75
 76		*(cast(ulong*)&buffer[$-8]) = FromBigEndian64(message.length * 8);
 77
 78		uint* bufferPtr = cast(uint*)&buffer[0];
 79		uint* bufferEnd = bufferPtr + (buffer.length / 8);
 80
 81		uint[64] words;
 82
 83		uint s0;
 84		uint s1;
 85		uint t1;
 86		uint t2;
 87		uint ch;
 88		uint maj;
 89
 90		uint a,b,c,d,e,f,g,h;
 91
 92		//Process the message in successive 512-bit chunks:
 93		while (bufferPtr < bufferEnd) {
 94			//Extend the sixteen 32-bit words into sixty-four 32-bit words:
 95			int i;
 96			for (; i < 16; i++) {
 97				words[i] = FromBigEndian32(bufferPtr[i]);
 98			}
 99			for (i=0; i < 48; i++) {
100				s0 = ((words[i+1] >>> 7) | (words[i+1] << 25)) ^ ((words[i+1] >>> 18) | (words[i+1] << 14)) ^ ((words[i+1] >>> 3));
101				s1 = ((words[i+14] >>> 17) | (words[i+14] << 15)) ^ ((words[i+14] >>> 19) | (words[i+14] << 13)) ^ ((words[i+14] >>> 10));
102				words[i+16] = words[i] + s0 + words[i+9] + s1;
103		    }
104
105		    //Initialize hash value for this chunk:
106			a = h0;	b = h1;	c = h2;	d = h3;
107			e = h4;	f = h5;	g = h6;	h = h7;
108
109		    for (i=0; i<64; i++) {
110				s0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10));
111				maj = (a & b) ^ (a & c) ^ (b & c);
112				t2 = s0 + maj;
113		        s1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7));
114		        ch = (e & f) ^ ((~e) & g);
115		        t1 = h + s1 + ch + k[i] + words[i];
116
117		        h = g;
118		        g = f;
119		        f = e;
120		        e = d + t1;
121		        d = c;
122		        c = b;
123		        b = a;
124		        a = t1 + t2;
125		    }
126
127		    //Add this chunk's hash to result so far:
128		    h0 += a; h1 += b; h2 += c; h3 += d;
129			h4 += e; h5 += f; h6 += g; h7 += h;
130
131		    bufferPtr += 16;
132		}
133
134		/*h0 = NativeToBE32(h0);
135		h1 = NativeToBE32(h1);
136		h2 = NativeToBE32(h2);
137		h3 = NativeToBE32(h3);
138		h4 = NativeToBE32(h4);*/
139
140		//Produce the final hash value (big-endian):
141		//digest = hash = h0 append h1 append h2 append h3 append h4
142		return new Digest(h0,h1,h2,h3,h4,h5,h6,h7);
143	}
144
145	// Description: This function will calculate the SHA-1 hash of a UTF8 encoded string.
146	// utf8Message: The string to hash.
147	// Returns: A string representing the SHA-1 hash.
148	Digest hash(string utf8Message) {
149		return hash(cast(ubyte[])utf8Message);
150	}
151
152	alias hash opCall;
153}