#include #include #include #include #include static uint64_t pad_length(uint64_t len) { uint64_t space_needed = 1; while(((len + space_needed) % 64) != 56) { space_needed += 1; } return space_needed; } static uint32_t rotate(uint8_t bits, uint32_t word) { return (word << bits) | (word >> (32 - bits)); } unsigned char *sha1(const char *msg, uint64_t len) { uint64_t ml = len * CHAR_BIT; uint64_t needed = pad_length(len); unsigned char *buf = malloc(len + needed + 8); if(buf == NULL) { return NULL; } strncpy((char *) buf, msg, len); buf[len++] = 0x80; for(; needed > 1; --needed) { buf[len++] = 0x00; } uint8_t count = 8; while(count--) { buf[len++] = (ml & ((uint64_t) 0xFF << 56)) >> 56; ml = ml << 8; } uint32_t h[] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }; uint64_t chunk = 0; for(; chunk < len; chunk += 64) { uint32_t w[80] = { 0 }; uint8_t i = 0; for(; i < 16; i++) { w[i] = buf[chunk + (i * 4)] << 24; w[i] |= buf[chunk + (i * 4 + 1)] << 16; w[i] |= buf[chunk + (i * 4 + 2)] << 8; w[i] |= buf[chunk + (i * 4 + 3)]; } for(i = 16; i < 80; ++i) { w[i] = rotate(1, w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]); } uint32_t a = h[0]; uint32_t b = h[1]; uint32_t c = h[2]; uint32_t d = h[3]; uint32_t e = h[4]; for(i = 0; i < 80; ++i) { uint32_t f = 0; uint32_t k = 0; if(i >= 0 && i <= 19) { f = (b & c) | ((~b) & d); k = (uint32_t) 0x5A827999; } else if(i >= 20 && i <= 39) { f = b ^ c ^ d; k = (uint32_t) 0x6ED9EBA1; } else if(i >= 40 && i <= 59) { f = (b & c) | (b & d) | (c & d); k = (uint32_t) 0x8F1BBCDC; } else if(i >= 60 && i <= 79) { f = b ^ c ^ d; k = (uint32_t) 0xCA62C1D6; } uint32_t temp = rotate(5, a) + f + e + k + w[i]; e = d; d = c; c = rotate(30, b); b = a; a = temp; } h[0] += a; h[1] += b; h[2] += c; h[3] += d; h[4] += e; } unsigned char *hh = malloc(20); if(hh == NULL) { return NULL; } for(count = 0; count < 5; count++) { hh[count * 4] = h[count] >> 24; hh[(count * 4) + 1] = (h[count] >> 16) & 0xFF; hh[(count * 4) + 2] = (h[count] >> 8) & 0xFF; hh[(count * 4) + 3] = h[count] & 0xFF; } return hh; } int main(int argc, char **argv) { for(++argv; argc > 1; ++argv, --argc) { unsigned char *hash = sha1(*argv, strlen(*argv)); uint8_t count = 0; for(; count < 20; ++count) { printf("%02X", (unsigned) hash[count]); } printf("\n"); } return 0; }