A fine-tuned implementation of the SHA256 hashing algorithm.
Dependents: EntropySource Wallet_v1
SHA256.cpp
00001 // Author: Remco Bloemen 00002 // Based on: 00003 // http://en.wikipedia.org/wiki/SHA-2 00004 // http://www.iwar.org.uk/comsec/resources/cipher/sha256-384-512.pdf 00005 // some of the OpenSSL optimizations 00006 00007 #include "SHA256.h" 00008 00009 inline unsigned int reverse_bytes(unsigned int x) 00010 { 00011 return __rev(x); 00012 } 00013 00014 inline unsigned int rotate_right(unsigned int x, int shift) 00015 { 00016 // return (x >> shift) | (x << (32 - shift)); 00017 return __ror(x, shift); 00018 } 00019 00020 void SHA256::reset() 00021 { 00022 hash[0] = 0x6A09E667; 00023 hash[1] = 0xBB67AE85; 00024 hash[2] = 0x3C6EF372; 00025 hash[3] = 0xA54FF53A; 00026 hash[4] = 0x510E527F; 00027 hash[5] = 0x9B05688C; 00028 hash[6] = 0x1F83D9AB; 00029 hash[7] = 0x5BE0CD19; 00030 length = 0; 00031 } 00032 00033 void SHA256::append(const char* data, int size) 00034 { 00035 int index = length % 64; 00036 length += size; 00037 const char* end = data + size; 00038 00039 // Word align data 00040 char* bytes = reinterpret_cast<char*>(w + (index / 4)); 00041 switch(index % 4) 00042 { 00043 // Remember to reverse! (little endian!) 00044 case 1: bytes[2] = *data++; ++index; 00045 case 2: bytes[1] = *data++; ++index; 00046 case 3: bytes[0] = *data++; ++index; 00047 case 0: break; 00048 } 00049 if(data > end) { 00050 // We have overshot reading data 00051 // but w and length are correct 00052 return; 00053 } 00054 00055 // Index is now word alligned 00056 index /= 4; 00057 if(index == 16) { 00058 process_chunk(); 00059 index = 0; 00060 } 00061 00062 // Process whole words 00063 int num_words = (end - data) / 4; 00064 const unsigned int* data_words = reinterpret_cast<const unsigned int*>(data); 00065 const unsigned int* data_words_end = data_words + num_words; 00066 while(data_words != data_words_end) 00067 { 00068 w[index++] = reverse_bytes(*data_words++); 00069 if(index == 16) { 00070 process_chunk(); 00071 index = 0; 00072 } 00073 } 00074 00075 // Process trailing data bytes 00076 // Again, we won't worry about overshooting data 00077 w[index] = reverse_bytes(*data_words); 00078 } 00079 00080 void SHA256::finalize() 00081 { 00082 int trailing = length % 64; 00083 00084 // Append the bit '1' to the message 00085 int last_block = trailing / 4; 00086 unsigned int bit_in_block = 0x80 << (24 - (trailing % 4) * 8); 00087 w[last_block] |= bit_in_block; 00088 00089 // Set all other bits to zero 00090 w[last_block] &= ~(bit_in_block - 1); 00091 for(int i = last_block + 1; i < 16; ++i) 00092 w[i] = 0; 00093 00094 // Make room for the length if necessary 00095 if(trailing >= 56) { 00096 process_chunk(); 00097 for(int i = 0; i <= last_block; ++i) 00098 w[i] = 0; 00099 } 00100 00101 // Append the length in bits 00102 w[14] = length >> (32 - 3); 00103 w[15] = length << 3; 00104 process_chunk(); 00105 00106 // Convert the result to big endian 00107 for(int i = 0; i < 8; ++i) 00108 hash[i] = reverse_bytes(hash[i]); 00109 } 00110 00111 #define s0(x) (rotate_right(x, 7) ^ rotate_right(x, 18) ^ (x >> 3)) 00112 #define s1(x) (rotate_right(x, 17) ^ rotate_right(x, 19) ^ (x >> 10)) 00113 #define s2(x) (rotate_right(x, 2) ^ rotate_right(x, 13) ^ rotate_right(x, 22)) 00114 #define s3(x) (rotate_right(x, 6) ^ rotate_right(x, 11) ^ rotate_right(x, 25)) 00115 #define maj(a,b,c) ((a & b) ^ (a & c) ^ (b & c)) 00116 #define ch(a,b,c) ((a & b) ^ ((~a) & c)) 00117 00118 const unsigned int k[64] = { 00119 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 00120 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 00121 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 00122 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, 00123 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 00124 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 00125 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 00126 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 00127 }; 00128 00129 #define ROUND(a,b,c,d,e,f,g,h,i) \ 00130 h += w[i];\ 00131 h += *K++;\ 00132 h += s3(e); \ 00133 h += ch(e, f, g); \ 00134 d += h;\ 00135 h += s2(a);\ 00136 h += maj(a, b, c); 00137 00138 #define W(n) w[(n) & 0xf] 00139 00140 #define ROUND2(a,b,c,d,e,f,g,h,i) \ 00141 W(i) += s0(W(i+1)) + W(i+9) + s1(W(i+14));\ 00142 h += W(i); \ 00143 h += *K++;\ 00144 h += s3(e);\ 00145 h += ch(e, f, g); \ 00146 d += h;\ 00147 h += s2(a);\ 00148 h += maj(a, b, c); 00149 00150 // Process a 512 bit chunk stored in w[1...15] 00151 void SHA256::process_chunk() 00152 { 00153 // Initialize using current hash 00154 unsigned int a = hash[0]; 00155 unsigned int b = hash[1]; 00156 unsigned int c = hash[2]; 00157 unsigned int d = hash[3]; 00158 unsigned int e = hash[4]; 00159 unsigned int f = hash[5]; 00160 unsigned int g = hash[6]; 00161 unsigned int h = hash[7]; 00162 00163 // Main loop 00164 const unsigned int* K = k; 00165 const unsigned int* K_end = k + 64; 00166 ROUND(a,b,c,d,e,f,g,h,0); 00167 ROUND(h,a,b,c,d,e,f,g,1); 00168 ROUND(g,h,a,b,c,d,e,f,2); 00169 ROUND(f,g,h,a,b,c,d,e,3); 00170 ROUND(e,f,g,h,a,b,c,d,4); 00171 ROUND(d,e,f,g,h,a,b,c,5); 00172 ROUND(c,d,e,f,g,h,a,b,6); 00173 ROUND(b,c,d,e,f,g,h,a,7); 00174 ROUND(a,b,c,d,e,f,g,h,8); 00175 ROUND(h,a,b,c,d,e,f,g,9); 00176 ROUND(g,h,a,b,c,d,e,f,10); 00177 ROUND(f,g,h,a,b,c,d,e,11); 00178 ROUND(e,f,g,h,a,b,c,d,12); 00179 ROUND(d,e,f,g,h,a,b,c,13); 00180 ROUND(c,d,e,f,g,h,a,b,14); 00181 ROUND(b,c,d,e,f,g,h,a,15); 00182 do { 00183 ROUND2(a,b,c,d,e,f,g,h,0); 00184 ROUND2(h,a,b,c,d,e,f,g,1); 00185 ROUND2(g,h,a,b,c,d,e,f,2); 00186 ROUND2(f,g,h,a,b,c,d,e,3); 00187 ROUND2(e,f,g,h,a,b,c,d,4); 00188 ROUND2(d,e,f,g,h,a,b,c,5); 00189 ROUND2(c,d,e,f,g,h,a,b,6); 00190 ROUND2(b,c,d,e,f,g,h,a,7); 00191 ROUND2(a,b,c,d,e,f,g,h,8); 00192 ROUND2(h,a,b,c,d,e,f,g,9); 00193 ROUND2(g,h,a,b,c,d,e,f,10); 00194 ROUND2(f,g,h,a,b,c,d,e,11); 00195 ROUND2(e,f,g,h,a,b,c,d,12); 00196 ROUND2(d,e,f,g,h,a,b,c,13); 00197 ROUND2(c,d,e,f,g,h,a,b,14); 00198 ROUND2(b,c,d,e,f,g,h,a,15); 00199 } while(K != K_end); 00200 00201 // Update hash 00202 hash[0] += a; 00203 hash[1] += b; 00204 hash[2] += c; 00205 hash[3] += d; 00206 hash[4] += e; 00207 hash[5] += f; 00208 hash[6] += g; 00209 hash[7] += h; 00210 } 00211 00212 std::string SHA256::hexString() 00213 { 00214 const char* hex = "0123456789abcdef"; 00215 std::string hexstr(64, '0'); 00216 for(int i = 0; i < 32; ++i) { 00217 hexstr[2 * i + 0] = hex[digest()[i] >> 4]; 00218 hexstr[2 * i + 1] = hex[digest()[i] & 0xf]; 00219 } 00220 return hexstr; 00221 }
Generated on Fri Jul 15 2022 02:57:12 by 1.7.2