117 lines
2.2 KiB
C
117 lines
2.2 KiB
C
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
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;
|
|
}
|