The SHA-1, produces a 160-bit message digest for a given data stream. It should take about 2**n steps to find a message with the same digest as a given message and 2**(n/2) to find any two messages with the same digest, when n is the digest size in bits. Therefore, this algorithm can serve as a means of providing a "fingerprint" for a message.
Portability Issues: SHA-1 is defined in terms of 32-bit "words". This code uses <stdint.h> (included via "sha1.h" to define 32 and 8 bit unsigned integer types. If your C compiler does not support 32 bit unsigned integers, this code is not appropriate.
Caveats: SHA-1 is designed to work with messages less than 2^64 bits long. Although SHA-1 allows a message digest to be generated for messages of any number of bits less than 2^64, this implementation only works with messages with a length that is a multiple of the size of an 8-bit character.
Definition in file sha1.cpp.
#include "stdmisc.h"
#include <stdio.h>
#include <string.h>
#include <string>
#include <map>
#include <vector>
#include "nel/misc/sha1.h"
#include "nel/misc/file.h"
#include "nel/misc/path.h"
Go to the source code of this file.
Data Structures | |
struct | SHA1Context |
Defines | |
#define | SHA1CircularShift(bits, word) (((word) << (bits)) | ((word) >> (32-(bits)))) |
#define | SHA1HashSize 20 |
Typedefs | |
typedef short | int_least16_t |
typedef SHA1Context | SHA1Context |
typedef unsigned int | uint32_t |
typedef unsigned char | uint8_t |
Enumerations | |
enum | { shaSuccess = 0, shaNull, shaInputTooLong, shaStateError } |
Functions | |
CHashKey | getSHA1 (const string &filename) |
CHashKey | getSHA1 (const uint8 *buffer, uint32 size) |
int | SHA1Input (SHA1Context *, const uint8_t *, unsigned int) |
void | SHA1PadMessage (SHA1Context *) |
void | SHA1ProcessMessageBlock (SHA1Context *) |
int | SHA1Reset (SHA1Context *) |
int | SHA1Result (SHA1Context *, uint8_t Message_Digest[20]) |
Variables | |
uint8_t | buffer [bufferSize] |
const int | bufferSize = 100000 |
|
Definition at line 235 of file sha1.cpp. Referenced by SHA1ProcessMessageBlock(). |
|
Definition at line 106 of file sha1.cpp. Referenced by SHA1Result(). |
|
|
|
|
|
Definition at line 87 of file sha1.cpp. Referenced by SHA1ProcessMessageBlock(). |
|
Definition at line 88 of file sha1.cpp. Referenced by getSHA1(). |
|
Definition at line 98 of file sha1.cpp.
00099 { 00100 shaSuccess = 0, 00101 shaNull, /* Null pointer parameter */ 00102 shaInputTooLong, /* input data too long */ 00103 shaStateError /* called Input after Result */ 00104 }; |
|
Definition at line 170 of file sha1.cpp. References buffer, bufferSize, NLMISC::CIFile::close(), NLMISC::CIFile::eof(), NLMISC::CIFile::getFileSize(), min, nlwarning, NLMISC::CIFile::open(), NLMISC::CIFile::serialBuffer(), NLMISC::CIFile::setCacheFileOnOpen(), SHA1Input(), SHA1Reset(), SHA1Result(), sint, uint8, and uint8_t.
00171 { 00172 SHA1Context sha; 00173 int err; 00174 uint8_t Message_Digest[20]; 00175 00176 //printf("reading '%s'\n", findData.cFileName); 00177 CIFile ifile; 00178 ifile.setCacheFileOnOpen(true); 00179 if (!ifile.open(CPath::lookup(filename))) 00180 { 00181 nlwarning ("SHA: Can't open the file '%s'", filename.c_str()); 00182 return CHashKey(); 00183 } 00184 00185 //FILE *fp = fopen (filename.c_str(), "rb"); 00186 //if (fp == NULL) return CHashKey(); 00187 00188 err = SHA1Reset(&sha); 00189 if (err) 00190 { 00191 nlwarning("SHA: SHA1Reset Error %d.\n", err ); 00192 ifile.close (); 00193 return CHashKey(); 00194 } 00195 00196 sint fs = ifile.getFileSize(); 00197 sint n, read = 0; 00198 do 00199 { 00200 //bs = (int)fread (buffer, 1, bufferSize, fp); 00201 n = std::min (bufferSize, fs-read); 00202 //nlinfo ("read %d bytes", n); 00203 ifile.serialBuffer((uint8 *)buffer, n); 00204 00205 err = SHA1Input(&sha, buffer, n); 00206 if (err) 00207 { 00208 nlwarning ("SHA: SHA1Input Error %d.\n", err); 00209 ifile.close(); 00210 return CHashKey(); 00211 } 00212 read += n; 00213 } 00214 while (!ifile.eof()); 00215 00216 ifile.close (); 00217 00218 err = SHA1Result(&sha, Message_Digest); 00219 if (err) 00220 { 00221 nlwarning("SHA: SHA1Result Error %d, could not compute message digest.\n", err ); 00222 return CHashKey(); 00223 } 00224 00225 CHashKey hk (Message_Digest); 00226 return hk; 00227 } |
|
Definition at line 139 of file sha1.cpp.
00140 { 00141 SHA1Context sha; 00142 int err; 00143 uint8_t Message_Digest[20]; 00144 00145 err = SHA1Reset(&sha); 00146 if (err) 00147 { 00148 nlwarning("SHA: SHA1Reset Error %d.\n", err ); 00149 return CHashKey(); 00150 } 00151 00152 err = SHA1Input(&sha, (const uint8_t*)buffer, size); 00153 if (err) 00154 { 00155 nlwarning ("SHA: SHA1Input Error %d.\n", err); 00156 return CHashKey(); 00157 } 00158 00159 err = SHA1Result(&sha, Message_Digest); 00160 if (err) 00161 { 00162 nlwarning("SHA: SHA1Result Error %d, could not compute message digest.\n", err ); 00163 return CHashKey(); 00164 } 00165 00166 CHashKey hk (Message_Digest); 00167 return hk; 00168 } |
|
Definition at line 357 of file sha1.cpp. References SHA1Context::Computed, SHA1Context::Corrupted, SHA1Context::Length_High, SHA1Context::Length_Low, SHA1Context::Message_Block, SHA1Context::Message_Block_Index, SHA1ProcessMessageBlock(), shaNull, shaStateError, and shaSuccess. Referenced by getSHA1().
00360 { 00361 if (!length) 00362 { 00363 return shaSuccess; 00364 } 00365 00366 if (!context || !message_array) 00367 { 00368 return shaNull; 00369 } 00370 00371 if (context->Computed) 00372 { 00373 context->Corrupted = shaStateError; 00374 00375 return shaStateError; 00376 } 00377 00378 if (context->Corrupted) 00379 { 00380 return context->Corrupted; 00381 } 00382 while(length-- && !context->Corrupted) 00383 { 00384 context->Message_Block[context->Message_Block_Index++] = 00385 (*message_array & 0xFF); 00386 00387 context->Length_Low += 8; 00388 if (context->Length_Low == 0) 00389 { 00390 context->Length_High++; 00391 if (context->Length_High == 0) 00392 { 00393 /* Message is too long */ 00394 context->Corrupted = 1; 00395 } 00396 } 00397 00398 if (context->Message_Block_Index == 64) 00399 { 00400 SHA1ProcessMessageBlock(context); 00401 } 00402 00403 message_array++; 00404 } 00405 00406 return shaSuccess; 00407 } |
|
Definition at line 541 of file sha1.cpp. References SHA1Context::Length_High, SHA1Context::Length_Low, SHA1Context::Message_Block, SHA1Context::Message_Block_Index, and SHA1ProcessMessageBlock(). Referenced by SHA1Result().
00542 { 00543 /* 00544 * Check to see if the current message block is too small to hold 00545 * the initial padding bits and length. If so, we will pad the 00546 * block, process it, and then continue padding into a second 00547 * block. 00548 */ 00549 if (context->Message_Block_Index > 55) 00550 { 00551 context->Message_Block[context->Message_Block_Index++] = 0x80; 00552 while(context->Message_Block_Index < 64) 00553 { 00554 context->Message_Block[context->Message_Block_Index++] = 0; 00555 } 00556 00557 SHA1ProcessMessageBlock(context); 00558 00559 while(context->Message_Block_Index < 56) 00560 { 00561 context->Message_Block[context->Message_Block_Index++] = 0; 00562 } 00563 } 00564 else 00565 { 00566 context->Message_Block[context->Message_Block_Index++] = 0x80; 00567 while(context->Message_Block_Index < 56) 00568 { 00569 00570 context->Message_Block[context->Message_Block_Index++] = 0; 00571 } 00572 } 00573 00574 /* 00575 * Store the message length as the last 8 octets 00576 */ 00577 context->Message_Block[56] = context->Length_High >> 24; 00578 context->Message_Block[57] = context->Length_High >> 16; 00579 context->Message_Block[58] = context->Length_High >> 8; 00580 context->Message_Block[59] = context->Length_High; 00581 context->Message_Block[60] = context->Length_Low >> 24; 00582 context->Message_Block[61] = context->Length_Low >> 16; 00583 context->Message_Block[62] = context->Length_Low >> 8; 00584 context->Message_Block[63] = context->Length_Low; 00585 00586 SHA1ProcessMessageBlock(context); 00587 } |
|
Definition at line 430 of file sha1.cpp. References SHA1Context::Intermediate_Hash, SHA1Context::Message_Block, SHA1Context::Message_Block_Index, SHA1CircularShift, t, and uint32_t. Referenced by SHA1Input(), and SHA1PadMessage().
00431 { 00432 const uint32_t K[] = { /* Constants defined in SHA-1 */ 00433 0x5A827999, 00434 0x6ED9EBA1, 00435 0x8F1BBCDC, 00436 0xCA62C1D6 00437 }; 00438 int t; /* Loop counter */ 00439 uint32_t temp; /* Temporary word value */ 00440 uint32_t W[80]; /* Word sequence */ 00441 uint32_t A, B, C, D, E; /* Word buffers */ 00442 00443 /* 00444 * Initialize the first 16 words in the array W 00445 */ 00446 for(t = 0; t < 16; t++) 00447 { 00448 W[t] = context->Message_Block[t * 4] << 24; 00449 W[t] |= context->Message_Block[t * 4 + 1] << 16; 00450 W[t] |= context->Message_Block[t * 4 + 2] << 8; 00451 W[t] |= context->Message_Block[t * 4 + 3]; 00452 } 00453 00454 for(t = 16; t < 80; t++) 00455 { 00456 W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); 00457 } 00458 00459 A = context->Intermediate_Hash[0]; 00460 B = context->Intermediate_Hash[1]; 00461 C = context->Intermediate_Hash[2]; 00462 D = context->Intermediate_Hash[3]; 00463 E = context->Intermediate_Hash[4]; 00464 00465 for(t = 0; t < 20; t++) 00466 { 00467 temp = SHA1CircularShift(5,A) + 00468 ((B & C) | ((~B) & D)) + E + W[t] + K[0]; 00469 E = D; 00470 D = C; 00471 C = SHA1CircularShift(30,B); 00472 00473 B = A; 00474 A = temp; 00475 } 00476 00477 for(t = 20; t < 40; t++) 00478 { 00479 temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; 00480 E = D; 00481 D = C; 00482 C = SHA1CircularShift(30,B); 00483 B = A; 00484 A = temp; 00485 } 00486 00487 for(t = 40; t < 60; t++) 00488 { 00489 temp = SHA1CircularShift(5,A) + 00490 ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; 00491 E = D; 00492 D = C; 00493 C = SHA1CircularShift(30,B); 00494 B = A; 00495 A = temp; 00496 } 00497 00498 for(t = 60; t < 80; t++) 00499 { 00500 temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; 00501 E = D; 00502 D = C; 00503 C = SHA1CircularShift(30,B); 00504 B = A; 00505 A = temp; 00506 } 00507 00508 context->Intermediate_Hash[0] += A; 00509 context->Intermediate_Hash[1] += B; 00510 context->Intermediate_Hash[2] += C; 00511 context->Intermediate_Hash[3] += D; 00512 context->Intermediate_Hash[4] += E; 00513 00514 context->Message_Block_Index = 0; 00515 } |
|
Definition at line 257 of file sha1.cpp. References SHA1Context::Computed, SHA1Context::Corrupted, SHA1Context::Intermediate_Hash, SHA1Context::Length_High, SHA1Context::Length_Low, SHA1Context::Message_Block_Index, shaNull, and shaSuccess. Referenced by getSHA1().
00258 { 00259 if (!context) 00260 { 00261 return shaNull; 00262 } 00263 00264 context->Length_Low = 0; 00265 context->Length_High = 0; 00266 context->Message_Block_Index = 0; 00267 00268 context->Intermediate_Hash[0] = 0x67452301; 00269 context->Intermediate_Hash[1] = 0xEFCDAB89; 00270 context->Intermediate_Hash[2] = 0x98BADCFE; 00271 context->Intermediate_Hash[3] = 0x10325476; 00272 context->Intermediate_Hash[4] = 0xC3D2E1F0; 00273 00274 context->Computed = 0; 00275 context->Corrupted = 0; 00276 00277 return shaSuccess; 00278 } |
|
Definition at line 299 of file sha1.cpp. References SHA1Context::Computed, SHA1Context::Corrupted, SHA1Context::Intermediate_Hash, SHA1Context::Length_High, SHA1Context::Length_Low, SHA1Context::Message_Block, SHA1HashSize, SHA1PadMessage(), shaNull, and shaSuccess. Referenced by getSHA1().
00301 { 00302 int i; 00303 00304 if (!context || !Message_Digest) 00305 { 00306 return shaNull; 00307 } 00308 00309 if (context->Corrupted) 00310 { 00311 return context->Corrupted; 00312 } 00313 00314 if (!context->Computed) 00315 { 00316 SHA1PadMessage(context); 00317 for(i=0; i<64; ++i) 00318 { 00319 /* message may be sensitive, clear it out */ 00320 context->Message_Block[i] = 0; 00321 } 00322 context->Length_Low = 0; /* and clear length */ 00323 context->Length_High = 0; 00324 context->Computed = 1; 00325 00326 } 00327 00328 for(i = 0; i < SHA1HashSize; ++i) 00329 { 00330 Message_Digest[i] = context->Intermediate_Hash[i>>2] 00331 >> 8 * ( 3 - ( i & 0x03 ) ); 00332 } 00333 00334 return shaSuccess; 00335 } |
|
|
|
Definition at line 95 of file sha1.cpp. Referenced by getSHA1(). |