#include <stdio.h>
// Code by: B-Con (http://b...content-available-to-author-only...n.us)
// Released under the GNU GPL
// MD5 Hash Digest implementation (little endian byte order)
#include <stdio.h>
// Signed variables are for wimps
#define uchar unsigned char
#define uint unsigned int
// DBL_INT_ADD treats two unsigned ints a and b as one 64-bit integer and adds c to it
#define ROTLEFT(a,b) ((a << b) | (a >> (32-b)))
#define DBL_INT_ADD(a,b,c) if (a > 0xffffffff - c) ++b; a += c;
typedef struct {
uchar data[64];
uint datalen;
uint bitlen[2];
uint state[5];
uint k[4];
} SHA1_CTX;
void sha1_transform(SHA1_CTX *ctx, uchar data[])
{
uint a,b,c,d,e,i,j,t,m[80];
for (i=0,j=0; i < 16; ++i, j += 4)
m[i] = (data[j] << 24) + (data[j+1] << 16) + (data[j+2] << 8) + (data[j+3]);
for ( ; i < 80; ++i) {
m[i] = (m[i-3] ^ m[i-8] ^ m[i-14] ^ m[i-16]);
m[i] = (m[i] << 1) | (m[i] >> 31);
}
a = ctx->state[0];
b = ctx->state[1];
c = ctx->state[2];
d = ctx->state[3];
e = ctx->state[4];
for (i=0; i < 20; ++i) {
t = ROTLEFT(a,5) + ((b & c) ^ (~b & d)) + e + ctx->k[0] + m[i];
e = d;
d = c;
c = ROTLEFT(b,30);
b = a;
a = t;
}
for ( ; i < 40; ++i) {
t = ROTLEFT(a,5) + (b ^ c ^ d) + e + ctx->k[1] + m[i];
e = d;
d = c;
c = ROTLEFT(b,30);
b = a;
a = t;
}
for ( ; i < 60; ++i) {
t = ROTLEFT(a,5) + ((b & c) ^ (b & d) ^ (c & d)) + e + ctx->k[2] + m[i];
e = d;
d = c;
c = ROTLEFT(b,30);
b = a;
a = t;
}
for ( ; i < 80; ++i) {
t = ROTLEFT(a,5) + (b ^ c ^ d) + e + ctx->k[3] + m[i];
e = d;
d = c;
c = ROTLEFT(b,30);
b = a;
a = t;
}
ctx->state[0] += a;
ctx->state[1] += b;
ctx->state[2] += c;
ctx->state[3] += d;
ctx->state[4] += e;
}
void sha1_init(SHA1_CTX *ctx)
{
ctx->datalen = 0;
ctx->bitlen[0] = 0;
ctx->bitlen[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xc3d2e1f0;
ctx->k[0] = 0x5a827999;
ctx->k[1] = 0x6ed9eba1;
ctx->k[2] = 0x8f1bbcdc;
ctx->k[3] = 0xca62c1d6;
}
void sha1_update(SHA1_CTX *ctx, uchar data[], uint len)
{
uint t,i;
for (i=0; i < len; ++i) {
ctx->data[ctx->datalen] = data[i];
ctx->datalen++;
if (ctx->datalen == 64) {
sha1_transform(ctx,ctx->data);
DBL_INT_ADD(ctx->bitlen[0],ctx->bitlen[1],512);
ctx->datalen = 0;
}
}
}
void sha1_final(SHA1_CTX *ctx, uchar hash[])
{
uint i;
i = ctx->datalen;
// Pad whatever data is left in the buffer.
if (ctx->datalen < 56) {
ctx->data[i++] = 0x80;
while (i < 56)
ctx->data[i++] = 0x00;
}
else {
ctx->data[i++] = 0x80;
while (i < 64)
ctx->data[i++] = 0x00;
sha1_transform(ctx,ctx->data);
}
// Append to the padding the total message's length in bits and transform.
DBL_INT_ADD(ctx->bitlen[0],ctx->bitlen[1],8 * ctx->datalen);
ctx->data[63] = ctx->bitlen[0];
ctx->data[62] = ctx->bitlen[0] >> 8;
ctx->data[61] = ctx->bitlen[0] >> 16;
ctx->data[60] = ctx->bitlen[0] >> 24;
ctx->data[59] = ctx->bitlen[1];
ctx->data[58] = ctx->bitlen[1] >> 8;
ctx->data[57] = ctx->bitlen[1] >> 16;
ctx->data[56] = ctx->bitlen[1] >> 24;
sha1_transform(ctx,ctx->data);
// Since this implementation uses little endian byte ordering and MD uses big endian,
// reverse all the bytes when copying the final state to the output hash.
for (i=0; i < 4; ++i) {
hash[i] = (ctx->state[0] >> (24-i*8)) & 0x000000ff;
hash[i+4] = (ctx->state[1] >> (24-i*8)) & 0x000000ff;
hash[i+8] = (ctx->state[2] >> (24-i*8)) & 0x000000ff;
hash[i+12] = (ctx->state[3] >> (24-i*8)) & 0x000000ff;
hash[i+16] = (ctx->state[4] >> (24-i*8)) & 0x000000ff;
}
}
int main(void) {
// your code goes here
SHA1_CTX hashctx;
unsigned char kisfaszom[3] = { 0x61, 0x62, 0x63 };
unsigned char hash[20];
sha1_init (&hashctx);
sha1_update (&hashctx, &kisfaszom[0], 2);
sha1_update (&hashctx, &kisfaszom[2], 1);
sha1_final(&hashctx, &hash[0]);
for (unsigned char i = 0; i<20; i++)
{
}
return 0;
}