#include #include #include #include typedef struct { uint32_t h0; uint32_t h1; uint32_t h2; uint32_t h3; uint32_t h4; } hash_t; hash_t* sha1(const char* s, hash_t* h); void printhash(hash_t* h); void main(int argc, char** argv) { hash_t h; const char* str; if(argc > 1) { str = argv[1]; } else { str = "test"; } sha1(str,&h); printhash(&h); } void printhash(hash_t* h) { printf("%08x%08x%08x%08x%08x\n", h->h0, h->h1, h->h2, h->h3, h->h4); } #define left_shift(n,X) (((X) << (n)) | ((X) >> (32-(n)))) void apply_round(const char* block, hash_t* state) { uint32_t A,B,C,D,E; uint32_t W[80]; uint32_t temp, K, f; for(int i = 0; i < 16; i++) { W[i] = (unsigned char)block[i*4] << 24; W[i] |= (unsigned char)block[i*4+1] << 16; W[i] |= (unsigned char)block[i*4+2] << 8; W[i] |= (unsigned char)block[i*4+3]; } for(int i = 16; i < 80; i++) { W[i] = left_shift(1, W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]); } A = state->h0; B = state->h1; C = state->h2; D = state->h3; E = state->h4; for(int i = 0; i < 80; i++) { if(0 <= i && i <= 19) { f = (B & C) | ( (~B) & D ); K = 0x5A827999; } else if(20 <= i && i <= 39) { f = B ^ C ^ D; K = 0x6ED9EBA1; } else if(40 <= i && i <= 59) { f = (B & C) | (B & D) | (C & D); K = 0x8F1BBCDC; } else if(60 <= i && i <= 79) { f = B ^ C ^ D; K = 0xCA62C1D6; } temp = left_shift(5,A) + f + E + W[i] + K; E = D; D = C; C = left_shift(30,B); B = A; A = temp; } state->h0 += A; state->h1 += B; state->h2 += C; state->h3 += D; state->h4 += E; } hash_t* sha1(const char* s, hash_t* H) { H->h0 = 0x67452301; H->h1 = 0xEFCDAB89; H->h2 = 0x98BADCFE; H->h3 = 0x10325476; H->h4 = 0xC3D2E1F0; size_t slen = strlen(s); size_t bitlen = slen*8; unsigned long long padlen = (slen + 64 - (slen%512)); if(padlen - slen < 8) padlen += 64; char buf[padlen]; memset(buf, 0, sizeof(char) * padlen); memcpy(buf, s, sizeof(char) * slen); buf[slen] = 0x80; for(int i = 0; i < 8; i++) { buf[padlen-i-1] = (bitlen >> (8*i)) & 0xFF; } size_t numblocks = padlen / 64; for(int i = 0; i < numblocks; i++) { apply_round(&(buf[i*64]),H); } return H; }