c/sha1.c: SHA1 hashing algorithm implementation
This commit is contained in:
parent
92515ff218
commit
daf6eeca41
|
@ -0,0 +1,137 @@
|
|||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
Loading…
Reference in New Issue