sha1.cpp (6744B)
1 /* 2 sha1.cpp - source code of 3 4 ============ 5 SHA-1 in C++ 6 ============ 7 8 100% Public Domain. 9 10 Original C Code 11 -- Steve Reid <steve@edmweb.com> 12 Small changes to fit into bglibs 13 -- Bruce Guenter <bruce@untroubled.org> 14 Translation to simpler C++ Code 15 -- Volker Grabsch <vog@notjusthosting.com> 16 */ 17 18 #include "sha1.h" 19 #include <sstream> 20 #include <iomanip> 21 #include <fstream> 22 23 /* Help macros */ 24 #define SHA1_ROL(value, bits) (((value) << (bits)) | (((value) & 0xffffffff) >> (32 - (bits)))) 25 #define SHA1_BLK(i) (block[i&15] = SHA1_ROL(block[(i+13)&15] ^ block[(i+8)&15] ^ block[(i+2)&15] ^ block[i&15],1)) 26 27 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 28 #define SHA1_R0(v,w,x,y,z,i) z += ((w&(x^y))^y) + block[i] + 0x5a827999 + SHA1_ROL(v,5); w=SHA1_ROL(w,30); 29 #define SHA1_R1(v,w,x,y,z,i) z += ((w&(x^y))^y) + SHA1_BLK(i) + 0x5a827999 + SHA1_ROL(v,5); w=SHA1_ROL(w,30); 30 #define SHA1_R2(v,w,x,y,z,i) z += (w^x^y) + SHA1_BLK(i) + 0x6ed9eba1 + SHA1_ROL(v,5); w=SHA1_ROL(w,30); 31 #define SHA1_R3(v,w,x,y,z,i) z += (((w|x)&y)|(w&x)) + SHA1_BLK(i) + 0x8f1bbcdc + SHA1_ROL(v,5); w=SHA1_ROL(w,30); 32 #define SHA1_R4(v,w,x,y,z,i) z += (w^x^y) + SHA1_BLK(i) + 0xca62c1d6 + SHA1_ROL(v,5); w=SHA1_ROL(w,30); 33 34 SHA1::SHA1() 35 { 36 reset(); 37 } 38 39 40 void SHA1::update(const std::string &s) 41 { 42 std::istringstream is(s); 43 update(is); 44 } 45 46 47 void SHA1::update(std::istream &is) 48 { 49 std::string rest_of_buffer; 50 read(is, rest_of_buffer, BLOCK_BYTES - buffer.size()); 51 buffer += rest_of_buffer; 52 53 while (is) 54 { 55 uint32 block[BLOCK_INTS]; 56 buffer_to_block(buffer, block); 57 transform(block); 58 read(is, buffer, BLOCK_BYTES); 59 } 60 } 61 62 63 /* 64 * Add padding and return the message digest. 65 */ 66 67 std::string SHA1::final() 68 { 69 /* Total number of hashed bits */ 70 uint64 total_bits = (transforms*BLOCK_BYTES + buffer.size()) * 8; 71 72 /* Padding */ 73 buffer += 0x80; 74 unsigned int orig_size = buffer.size(); 75 while (buffer.size() < BLOCK_BYTES) 76 { 77 buffer += (char)0x00; 78 } 79 80 uint32 block[BLOCK_INTS]; 81 buffer_to_block(buffer, block); 82 83 if (orig_size > BLOCK_BYTES - 8) 84 { 85 transform(block); 86 for (unsigned int i = 0; i < BLOCK_INTS - 2; i++) 87 { 88 block[i] = 0; 89 } 90 } 91 92 /* Append total_bits, split this uint64 into two uint32 */ 93 block[BLOCK_INTS - 1] = total_bits; 94 block[BLOCK_INTS - 2] = (total_bits >> 32); 95 transform(block); 96 97 /* Hex std::string */ 98 std::ostringstream result; 99 for (unsigned int i = 0; i < DIGEST_INTS; i++) 100 { 101 result << std::hex << std::setfill('0') << std::setw(8); 102 result << (digest[i] & 0xffffffff); 103 } 104 105 /* Reset for next run */ 106 reset(); 107 108 return result.str(); 109 } 110 111 112 std::string SHA1::from_file(const std::string &filename) 113 { 114 std::ifstream stream(filename.c_str(), std::ios::binary); 115 SHA1 checksum; 116 checksum.update(stream); 117 return checksum.final(); 118 } 119 120 121 void SHA1::reset() 122 { 123 /* SHA1 initialization constants */ 124 digest[0] = 0x67452301; 125 digest[1] = 0xefcdab89; 126 digest[2] = 0x98badcfe; 127 digest[3] = 0x10325476; 128 digest[4] = 0xc3d2e1f0; 129 130 /* Reset counters */ 131 transforms = 0; 132 buffer = ""; 133 } 134 135 136 /* 137 * Hash a single 512-bit block. This is the core of the algorithm. 138 */ 139 140 void SHA1::transform(uint32 block[BLOCK_BYTES]) 141 { 142 /* Copy digest[] to working vars */ 143 uint32 a = digest[0]; 144 uint32 b = digest[1]; 145 uint32 c = digest[2]; 146 uint32 d = digest[3]; 147 uint32 e = digest[4]; 148 149 150 /* 4 rounds of 20 operations each. Loop unrolled. */ 151 SHA1_R0(a,b,c,d,e, 0); 152 SHA1_R0(e,a,b,c,d, 1); 153 SHA1_R0(d,e,a,b,c, 2); 154 SHA1_R0(c,d,e,a,b, 3); 155 SHA1_R0(b,c,d,e,a, 4); 156 SHA1_R0(a,b,c,d,e, 5); 157 SHA1_R0(e,a,b,c,d, 6); 158 SHA1_R0(d,e,a,b,c, 7); 159 SHA1_R0(c,d,e,a,b, 8); 160 SHA1_R0(b,c,d,e,a, 9); 161 SHA1_R0(a,b,c,d,e,10); 162 SHA1_R0(e,a,b,c,d,11); 163 SHA1_R0(d,e,a,b,c,12); 164 SHA1_R0(c,d,e,a,b,13); 165 SHA1_R0(b,c,d,e,a,14); 166 SHA1_R0(a,b,c,d,e,15); 167 SHA1_R1(e,a,b,c,d,16); 168 SHA1_R1(d,e,a,b,c,17); 169 SHA1_R1(c,d,e,a,b,18); 170 SHA1_R1(b,c,d,e,a,19); 171 SHA1_R2(a,b,c,d,e,20); 172 SHA1_R2(e,a,b,c,d,21); 173 SHA1_R2(d,e,a,b,c,22); 174 SHA1_R2(c,d,e,a,b,23); 175 SHA1_R2(b,c,d,e,a,24); 176 SHA1_R2(a,b,c,d,e,25); 177 SHA1_R2(e,a,b,c,d,26); 178 SHA1_R2(d,e,a,b,c,27); 179 SHA1_R2(c,d,e,a,b,28); 180 SHA1_R2(b,c,d,e,a,29); 181 SHA1_R2(a,b,c,d,e,30); 182 SHA1_R2(e,a,b,c,d,31); 183 SHA1_R2(d,e,a,b,c,32); 184 SHA1_R2(c,d,e,a,b,33); 185 SHA1_R2(b,c,d,e,a,34); 186 SHA1_R2(a,b,c,d,e,35); 187 SHA1_R2(e,a,b,c,d,36); 188 SHA1_R2(d,e,a,b,c,37); 189 SHA1_R2(c,d,e,a,b,38); 190 SHA1_R2(b,c,d,e,a,39); 191 SHA1_R3(a,b,c,d,e,40); 192 SHA1_R3(e,a,b,c,d,41); 193 SHA1_R3(d,e,a,b,c,42); 194 SHA1_R3(c,d,e,a,b,43); 195 SHA1_R3(b,c,d,e,a,44); 196 SHA1_R3(a,b,c,d,e,45); 197 SHA1_R3(e,a,b,c,d,46); 198 SHA1_R3(d,e,a,b,c,47); 199 SHA1_R3(c,d,e,a,b,48); 200 SHA1_R3(b,c,d,e,a,49); 201 SHA1_R3(a,b,c,d,e,50); 202 SHA1_R3(e,a,b,c,d,51); 203 SHA1_R3(d,e,a,b,c,52); 204 SHA1_R3(c,d,e,a,b,53); 205 SHA1_R3(b,c,d,e,a,54); 206 SHA1_R3(a,b,c,d,e,55); 207 SHA1_R3(e,a,b,c,d,56); 208 SHA1_R3(d,e,a,b,c,57); 209 SHA1_R3(c,d,e,a,b,58); 210 SHA1_R3(b,c,d,e,a,59); 211 SHA1_R4(a,b,c,d,e,60); 212 SHA1_R4(e,a,b,c,d,61); 213 SHA1_R4(d,e,a,b,c,62); 214 SHA1_R4(c,d,e,a,b,63); 215 SHA1_R4(b,c,d,e,a,64); 216 SHA1_R4(a,b,c,d,e,65); 217 SHA1_R4(e,a,b,c,d,66); 218 SHA1_R4(d,e,a,b,c,67); 219 SHA1_R4(c,d,e,a,b,68); 220 SHA1_R4(b,c,d,e,a,69); 221 SHA1_R4(a,b,c,d,e,70); 222 SHA1_R4(e,a,b,c,d,71); 223 SHA1_R4(d,e,a,b,c,72); 224 SHA1_R4(c,d,e,a,b,73); 225 SHA1_R4(b,c,d,e,a,74); 226 SHA1_R4(a,b,c,d,e,75); 227 SHA1_R4(e,a,b,c,d,76); 228 SHA1_R4(d,e,a,b,c,77); 229 SHA1_R4(c,d,e,a,b,78); 230 SHA1_R4(b,c,d,e,a,79); 231 232 /* Add the working vars back into digest[] */ 233 digest[0] += a; 234 digest[1] += b; 235 digest[2] += c; 236 digest[3] += d; 237 digest[4] += e; 238 239 /* Count the number of transformations */ 240 transforms++; 241 } 242 243 244 void SHA1::buffer_to_block(const std::string &buffer, uint32 block[BLOCK_BYTES]) 245 { 246 /* Convert the std::string (byte buffer) to a uint32 array (MSB) */ 247 for (unsigned int i = 0; i < BLOCK_INTS; i++) 248 { 249 block[i] = (buffer[4*i+3] & 0xff) 250 | (buffer[4*i+2] & 0xff)<<8 251 | (buffer[4*i+1] & 0xff)<<16 252 | (buffer[4*i+0] & 0xff)<<24; 253 } 254 } 255 256 257 void SHA1::read(std::istream &is, std::string &s, int max) 258 { 259 char sbuf[max]; 260 is.read(sbuf, max); 261 s.assign(sbuf, is.gcount()); 262 } 263 264 265 std::string sha1(const std::string &string) 266 { 267 SHA1 checksum; 268 checksum.update(string); 269 return checksum.final(); 270 }