From daf6eeca41a2eef8e07355824dc647e566c2832f Mon Sep 17 00:00:00 2001 From: Nick Chambers Date: Sun, 25 Jul 2021 20:37:10 -0500 Subject: [PATCH] c/sha1.c: SHA1 hashing algorithm implementation --- c/sha1.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 c/sha1.c diff --git a/c/sha1.c b/c/sha1.c new file mode 100644 index 0000000..9ba14d0 --- /dev/null +++ b/c/sha1.c @@ -0,0 +1,137 @@ +#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; +}