Mercurial > hg > orthanc
comparison Resources/sha1/sha1.cpp @ 177:81b6f3013738
sha1
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 09 Nov 2012 10:42:00 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
176:81f11fb357f2 | 177:81b6f3013738 |
---|---|
1 /* | |
2 * sha1.cpp | |
3 * | |
4 * Copyright (C) 1998, 2009 | |
5 * Paul E. Jones <paulej@packetizer.com> | |
6 * All Rights Reserved. | |
7 * | |
8 ***************************************************************************** | |
9 * $Id: sha1.cpp 12 2009-06-22 19:34:25Z paulej $ | |
10 ***************************************************************************** | |
11 * | |
12 * Description: | |
13 * This class implements the Secure Hashing Standard as defined | |
14 * in FIPS PUB 180-1 published April 17, 1995. | |
15 * | |
16 * The Secure Hashing Standard, which uses the Secure Hashing | |
17 * Algorithm (SHA), produces a 160-bit message digest for a | |
18 * given data stream. In theory, it is highly improbable that | |
19 * two messages will produce the same message digest. Therefore, | |
20 * this algorithm can serve as a means of providing a "fingerprint" | |
21 * for a message. | |
22 * | |
23 * Portability Issues: | |
24 * SHA-1 is defined in terms of 32-bit "words". This code was | |
25 * written with the expectation that the processor has at least | |
26 * a 32-bit machine word size. If the machine word size is larger, | |
27 * the code should still function properly. One caveat to that | |
28 * is that the input functions taking characters and character arrays | |
29 * assume that only 8 bits of information are stored in each character. | |
30 * | |
31 * Caveats: | |
32 * SHA-1 is designed to work with messages less than 2^64 bits long. | |
33 * Although SHA-1 allows a message digest to be generated for | |
34 * messages of any number of bits less than 2^64, this implementation | |
35 * only works with messages with a length that is a multiple of 8 | |
36 * bits. | |
37 * | |
38 */ | |
39 | |
40 | |
41 #include "sha1.h" | |
42 | |
43 /* | |
44 * SHA1 | |
45 * | |
46 * Description: | |
47 * This is the constructor for the sha1 class. | |
48 * | |
49 * Parameters: | |
50 * None. | |
51 * | |
52 * Returns: | |
53 * Nothing. | |
54 * | |
55 * Comments: | |
56 * | |
57 */ | |
58 SHA1::SHA1() | |
59 { | |
60 Reset(); | |
61 } | |
62 | |
63 /* | |
64 * ~SHA1 | |
65 * | |
66 * Description: | |
67 * This is the destructor for the sha1 class | |
68 * | |
69 * Parameters: | |
70 * None. | |
71 * | |
72 * Returns: | |
73 * Nothing. | |
74 * | |
75 * Comments: | |
76 * | |
77 */ | |
78 SHA1::~SHA1() | |
79 { | |
80 // The destructor does nothing | |
81 } | |
82 | |
83 /* | |
84 * Reset | |
85 * | |
86 * Description: | |
87 * This function will initialize the sha1 class member variables | |
88 * in preparation for computing a new message digest. | |
89 * | |
90 * Parameters: | |
91 * None. | |
92 * | |
93 * Returns: | |
94 * Nothing. | |
95 * | |
96 * Comments: | |
97 * | |
98 */ | |
99 void SHA1::Reset() | |
100 { | |
101 Length_Low = 0; | |
102 Length_High = 0; | |
103 Message_Block_Index = 0; | |
104 | |
105 H[0] = 0x67452301; | |
106 H[1] = 0xEFCDAB89; | |
107 H[2] = 0x98BADCFE; | |
108 H[3] = 0x10325476; | |
109 H[4] = 0xC3D2E1F0; | |
110 | |
111 Computed = false; | |
112 Corrupted = false; | |
113 } | |
114 | |
115 /* | |
116 * Result | |
117 * | |
118 * Description: | |
119 * This function will return the 160-bit message digest into the | |
120 * array provided. | |
121 * | |
122 * Parameters: | |
123 * message_digest_array: [out] | |
124 * This is an array of five unsigned integers which will be filled | |
125 * with the message digest that has been computed. | |
126 * | |
127 * Returns: | |
128 * True if successful, false if it failed. | |
129 * | |
130 * Comments: | |
131 * | |
132 */ | |
133 bool SHA1::Result(unsigned *message_digest_array) | |
134 { | |
135 int i; // Counter | |
136 | |
137 if (Corrupted) | |
138 { | |
139 return false; | |
140 } | |
141 | |
142 if (!Computed) | |
143 { | |
144 PadMessage(); | |
145 Computed = true; | |
146 } | |
147 | |
148 for(i = 0; i < 5; i++) | |
149 { | |
150 message_digest_array[i] = H[i]; | |
151 } | |
152 | |
153 return true; | |
154 } | |
155 | |
156 /* | |
157 * Input | |
158 * | |
159 * Description: | |
160 * This function accepts an array of octets as the next portion of | |
161 * the message. | |
162 * | |
163 * Parameters: | |
164 * message_array: [in] | |
165 * An array of characters representing the next portion of the | |
166 * message. | |
167 * | |
168 * Returns: | |
169 * Nothing. | |
170 * | |
171 * Comments: | |
172 * | |
173 */ | |
174 void SHA1::Input( const unsigned char *message_array, | |
175 unsigned length) | |
176 { | |
177 if (!length) | |
178 { | |
179 return; | |
180 } | |
181 | |
182 if (Computed || Corrupted) | |
183 { | |
184 Corrupted = true; | |
185 return; | |
186 } | |
187 | |
188 while(length-- && !Corrupted) | |
189 { | |
190 Message_Block[Message_Block_Index++] = (*message_array & 0xFF); | |
191 | |
192 Length_Low += 8; | |
193 Length_Low &= 0xFFFFFFFF; // Force it to 32 bits | |
194 if (Length_Low == 0) | |
195 { | |
196 Length_High++; | |
197 Length_High &= 0xFFFFFFFF; // Force it to 32 bits | |
198 if (Length_High == 0) | |
199 { | |
200 Corrupted = true; // Message is too long | |
201 } | |
202 } | |
203 | |
204 if (Message_Block_Index == 64) | |
205 { | |
206 ProcessMessageBlock(); | |
207 } | |
208 | |
209 message_array++; | |
210 } | |
211 } | |
212 | |
213 /* | |
214 * Input | |
215 * | |
216 * Description: | |
217 * This function accepts an array of octets as the next portion of | |
218 * the message. | |
219 * | |
220 * Parameters: | |
221 * message_array: [in] | |
222 * An array of characters representing the next portion of the | |
223 * message. | |
224 * length: [in] | |
225 * The length of the message_array | |
226 * | |
227 * Returns: | |
228 * Nothing. | |
229 * | |
230 * Comments: | |
231 * | |
232 */ | |
233 void SHA1::Input( const char *message_array, | |
234 unsigned length) | |
235 { | |
236 Input((unsigned char *) message_array, length); | |
237 } | |
238 | |
239 /* | |
240 * Input | |
241 * | |
242 * Description: | |
243 * This function accepts a single octets as the next message element. | |
244 * | |
245 * Parameters: | |
246 * message_element: [in] | |
247 * The next octet in the message. | |
248 * | |
249 * Returns: | |
250 * Nothing. | |
251 * | |
252 * Comments: | |
253 * | |
254 */ | |
255 void SHA1::Input(unsigned char message_element) | |
256 { | |
257 Input(&message_element, 1); | |
258 } | |
259 | |
260 /* | |
261 * Input | |
262 * | |
263 * Description: | |
264 * This function accepts a single octet as the next message element. | |
265 * | |
266 * Parameters: | |
267 * message_element: [in] | |
268 * The next octet in the message. | |
269 * | |
270 * Returns: | |
271 * Nothing. | |
272 * | |
273 * Comments: | |
274 * | |
275 */ | |
276 void SHA1::Input(char message_element) | |
277 { | |
278 Input((unsigned char *) &message_element, 1); | |
279 } | |
280 | |
281 /* | |
282 * operator<< | |
283 * | |
284 * Description: | |
285 * This operator makes it convenient to provide character strings to | |
286 * the SHA1 object for processing. | |
287 * | |
288 * Parameters: | |
289 * message_array: [in] | |
290 * The character array to take as input. | |
291 * | |
292 * Returns: | |
293 * A reference to the SHA1 object. | |
294 * | |
295 * Comments: | |
296 * Each character is assumed to hold 8 bits of information. | |
297 * | |
298 */ | |
299 SHA1& SHA1::operator<<(const char *message_array) | |
300 { | |
301 const char *p = message_array; | |
302 | |
303 while(*p) | |
304 { | |
305 Input(*p); | |
306 p++; | |
307 } | |
308 | |
309 return *this; | |
310 } | |
311 | |
312 /* | |
313 * operator<< | |
314 * | |
315 * Description: | |
316 * This operator makes it convenient to provide character strings to | |
317 * the SHA1 object for processing. | |
318 * | |
319 * Parameters: | |
320 * message_array: [in] | |
321 * The character array to take as input. | |
322 * | |
323 * Returns: | |
324 * A reference to the SHA1 object. | |
325 * | |
326 * Comments: | |
327 * Each character is assumed to hold 8 bits of information. | |
328 * | |
329 */ | |
330 SHA1& SHA1::operator<<(const unsigned char *message_array) | |
331 { | |
332 const unsigned char *p = message_array; | |
333 | |
334 while(*p) | |
335 { | |
336 Input(*p); | |
337 p++; | |
338 } | |
339 | |
340 return *this; | |
341 } | |
342 | |
343 /* | |
344 * operator<< | |
345 * | |
346 * Description: | |
347 * This function provides the next octet in the message. | |
348 * | |
349 * Parameters: | |
350 * message_element: [in] | |
351 * The next octet in the message | |
352 * | |
353 * Returns: | |
354 * A reference to the SHA1 object. | |
355 * | |
356 * Comments: | |
357 * The character is assumed to hold 8 bits of information. | |
358 * | |
359 */ | |
360 SHA1& SHA1::operator<<(const char message_element) | |
361 { | |
362 Input((unsigned char *) &message_element, 1); | |
363 | |
364 return *this; | |
365 } | |
366 | |
367 /* | |
368 * operator<< | |
369 * | |
370 * Description: | |
371 * This function provides the next octet in the message. | |
372 * | |
373 * Parameters: | |
374 * message_element: [in] | |
375 * The next octet in the message | |
376 * | |
377 * Returns: | |
378 * A reference to the SHA1 object. | |
379 * | |
380 * Comments: | |
381 * The character is assumed to hold 8 bits of information. | |
382 * | |
383 */ | |
384 SHA1& SHA1::operator<<(const unsigned char message_element) | |
385 { | |
386 Input(&message_element, 1); | |
387 | |
388 return *this; | |
389 } | |
390 | |
391 /* | |
392 * ProcessMessageBlock | |
393 * | |
394 * Description: | |
395 * This function will process the next 512 bits of the message | |
396 * stored in the Message_Block array. | |
397 * | |
398 * Parameters: | |
399 * None. | |
400 * | |
401 * Returns: | |
402 * Nothing. | |
403 * | |
404 * Comments: | |
405 * Many of the variable names in this function, especially the single | |
406 * character names, were used because those were the names used | |
407 * in the publication. | |
408 * | |
409 */ | |
410 void SHA1::ProcessMessageBlock() | |
411 { | |
412 const unsigned K[] = { // Constants defined for SHA-1 | |
413 0x5A827999, | |
414 0x6ED9EBA1, | |
415 0x8F1BBCDC, | |
416 0xCA62C1D6 | |
417 }; | |
418 int t; // Loop counter | |
419 unsigned temp; // Temporary word value | |
420 unsigned W[80]; // Word sequence | |
421 unsigned A, B, C, D, E; // Word buffers | |
422 | |
423 /* | |
424 * Initialize the first 16 words in the array W | |
425 */ | |
426 for(t = 0; t < 16; t++) | |
427 { | |
428 W[t] = ((unsigned) Message_Block[t * 4]) << 24; | |
429 W[t] |= ((unsigned) Message_Block[t * 4 + 1]) << 16; | |
430 W[t] |= ((unsigned) Message_Block[t * 4 + 2]) << 8; | |
431 W[t] |= ((unsigned) Message_Block[t * 4 + 3]); | |
432 } | |
433 | |
434 for(t = 16; t < 80; t++) | |
435 { | |
436 W[t] = CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); | |
437 } | |
438 | |
439 A = H[0]; | |
440 B = H[1]; | |
441 C = H[2]; | |
442 D = H[3]; | |
443 E = H[4]; | |
444 | |
445 for(t = 0; t < 20; t++) | |
446 { | |
447 temp = CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; | |
448 temp &= 0xFFFFFFFF; | |
449 E = D; | |
450 D = C; | |
451 C = CircularShift(30,B); | |
452 B = A; | |
453 A = temp; | |
454 } | |
455 | |
456 for(t = 20; t < 40; t++) | |
457 { | |
458 temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; | |
459 temp &= 0xFFFFFFFF; | |
460 E = D; | |
461 D = C; | |
462 C = CircularShift(30,B); | |
463 B = A; | |
464 A = temp; | |
465 } | |
466 | |
467 for(t = 40; t < 60; t++) | |
468 { | |
469 temp = CircularShift(5,A) + | |
470 ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; | |
471 temp &= 0xFFFFFFFF; | |
472 E = D; | |
473 D = C; | |
474 C = CircularShift(30,B); | |
475 B = A; | |
476 A = temp; | |
477 } | |
478 | |
479 for(t = 60; t < 80; t++) | |
480 { | |
481 temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; | |
482 temp &= 0xFFFFFFFF; | |
483 E = D; | |
484 D = C; | |
485 C = CircularShift(30,B); | |
486 B = A; | |
487 A = temp; | |
488 } | |
489 | |
490 H[0] = (H[0] + A) & 0xFFFFFFFF; | |
491 H[1] = (H[1] + B) & 0xFFFFFFFF; | |
492 H[2] = (H[2] + C) & 0xFFFFFFFF; | |
493 H[3] = (H[3] + D) & 0xFFFFFFFF; | |
494 H[4] = (H[4] + E) & 0xFFFFFFFF; | |
495 | |
496 Message_Block_Index = 0; | |
497 } | |
498 | |
499 /* | |
500 * PadMessage | |
501 * | |
502 * Description: | |
503 * According to the standard, the message must be padded to an even | |
504 * 512 bits. The first padding bit must be a '1'. The last 64 bits | |
505 * represent the length of the original message. All bits in between | |
506 * should be 0. This function will pad the message according to those | |
507 * rules by filling the message_block array accordingly. It will also | |
508 * call ProcessMessageBlock() appropriately. When it returns, it | |
509 * can be assumed that the message digest has been computed. | |
510 * | |
511 * Parameters: | |
512 * None. | |
513 * | |
514 * Returns: | |
515 * Nothing. | |
516 * | |
517 * Comments: | |
518 * | |
519 */ | |
520 void SHA1::PadMessage() | |
521 { | |
522 /* | |
523 * Check to see if the current message block is too small to hold | |
524 * the initial padding bits and length. If so, we will pad the | |
525 * block, process it, and then continue padding into a second block. | |
526 */ | |
527 if (Message_Block_Index > 55) | |
528 { | |
529 Message_Block[Message_Block_Index++] = 0x80; | |
530 while(Message_Block_Index < 64) | |
531 { | |
532 Message_Block[Message_Block_Index++] = 0; | |
533 } | |
534 | |
535 ProcessMessageBlock(); | |
536 | |
537 while(Message_Block_Index < 56) | |
538 { | |
539 Message_Block[Message_Block_Index++] = 0; | |
540 } | |
541 } | |
542 else | |
543 { | |
544 Message_Block[Message_Block_Index++] = 0x80; | |
545 while(Message_Block_Index < 56) | |
546 { | |
547 Message_Block[Message_Block_Index++] = 0; | |
548 } | |
549 | |
550 } | |
551 | |
552 /* | |
553 * Store the message length as the last 8 octets | |
554 */ | |
555 Message_Block[56] = (Length_High >> 24) & 0xFF; | |
556 Message_Block[57] = (Length_High >> 16) & 0xFF; | |
557 Message_Block[58] = (Length_High >> 8) & 0xFF; | |
558 Message_Block[59] = (Length_High) & 0xFF; | |
559 Message_Block[60] = (Length_Low >> 24) & 0xFF; | |
560 Message_Block[61] = (Length_Low >> 16) & 0xFF; | |
561 Message_Block[62] = (Length_Low >> 8) & 0xFF; | |
562 Message_Block[63] = (Length_Low) & 0xFF; | |
563 | |
564 ProcessMessageBlock(); | |
565 } | |
566 | |
567 | |
568 /* | |
569 * CircularShift | |
570 * | |
571 * Description: | |
572 * This member function will perform a circular shifting operation. | |
573 * | |
574 * Parameters: | |
575 * bits: [in] | |
576 * The number of bits to shift (1-31) | |
577 * word: [in] | |
578 * The value to shift (assumes a 32-bit integer) | |
579 * | |
580 * Returns: | |
581 * The shifted value. | |
582 * | |
583 * Comments: | |
584 * | |
585 */ | |
586 unsigned SHA1::CircularShift(int bits, unsigned word) | |
587 { | |
588 return ((word << bits) & 0xFFFFFFFF) | ((word & 0xFFFFFFFF) >> (32-bits)); | |
589 } |