/hashes/sha224.d

http://github.com/wilkie/djehuty · D · 153 lines · 91 code · 28 blank · 34 comment · 6 complexity · 1848151c55b60c1fa95e7505d7a8ec6c MD5 · raw file

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