120 lines
No EOL
3.1 KiB
C
120 lines
No EOL
3.1 KiB
C
#include "sha1.h"
|
|
|
|
sha1_t sha1_init(void) {
|
|
return (sha1_t) {
|
|
.digest = {
|
|
0x67452301,
|
|
0xEFCDAB89,
|
|
0x98BADCFE,
|
|
0x10325476,
|
|
0xC3D2E1F0,
|
|
},
|
|
};
|
|
}
|
|
|
|
uint32 sha1_left_rotate(uint32 value, uint32 count) {
|
|
return (value << count) ^ (value >> (32 - count));
|
|
}
|
|
|
|
void sha1_process_block(sha1_t *ctx) {
|
|
uint32 w [80];
|
|
for (usize i = 0; i < 16; ++i) {
|
|
w[i] = ctx->block[i * 4 + 0] << 24;
|
|
w[i] |= ctx->block[i * 4 + 1] << 16;
|
|
w[i] |= ctx->block[i * 4 + 2] << 8;
|
|
w[i] |= ctx->block[i * 4 + 3] << 0;
|
|
}
|
|
|
|
for (usize i = 16; i < 80; ++i) {
|
|
w[i] = sha1_left_rotate(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
|
|
}
|
|
|
|
uint32 a = ctx->digest[0];
|
|
uint32 b = ctx->digest[1];
|
|
uint32 c = ctx->digest[2];
|
|
uint32 d = ctx->digest[3];
|
|
uint32 e = ctx->digest[4];
|
|
|
|
for (usize i = 0; i < 80; ++i) {
|
|
uint32 f = 0;
|
|
uint32 k = 0;
|
|
|
|
if (i<20) {
|
|
f = (b & c) | (~b & d);
|
|
k = 0x5A827999;
|
|
} else if (i<40) {
|
|
f = b ^ c ^ d;
|
|
k = 0x6ED9EBA1;
|
|
} else if (i<60) {
|
|
f = (b & c) | (b & d) | (c & d);
|
|
k = 0x8F1BBCDC;
|
|
} else {
|
|
f = b ^ c ^ d;
|
|
k = 0xCA62C1D6;
|
|
}
|
|
uint32 temp = sha1_left_rotate(a, 5) + f + e + k + w[i];
|
|
e = d;
|
|
d = c;
|
|
c = sha1_left_rotate(b, 30);
|
|
b = a;
|
|
a = temp;
|
|
}
|
|
|
|
ctx->digest[0] += a;
|
|
ctx->digest[1] += b;
|
|
ctx->digest[2] += c;
|
|
ctx->digest[3] += d;
|
|
ctx->digest[4] += e;
|
|
}
|
|
|
|
void sha1_process_byte(sha1_t *ctx, uint8 b) {
|
|
ctx->block[ctx->block_index++] = b;
|
|
++ctx->byte_count;
|
|
if (ctx->block_index == 64) {
|
|
ctx->block_index = 0;
|
|
sha1_process_block(ctx);
|
|
}
|
|
}
|
|
|
|
sha1_result_t sha1(sha1_t *ctx, const void *buf, usize len) {
|
|
const uint8 *block = buf;
|
|
|
|
for (usize i = 0; i < len; ++i) {
|
|
sha1_process_byte(ctx, block[i]);
|
|
}
|
|
|
|
usize bitcount = ctx->byte_count * 8;
|
|
sha1_process_byte(ctx, 0x80);
|
|
|
|
if (ctx->block_index > 56) {
|
|
while (ctx->block_index != 0) {
|
|
sha1_process_byte(ctx, 0);
|
|
}
|
|
while (ctx->block_index < 56) {
|
|
sha1_process_byte(ctx, 0);
|
|
}
|
|
} else {
|
|
while (ctx->block_index < 56) {
|
|
sha1_process_byte(ctx, 0);
|
|
}
|
|
}
|
|
sha1_process_byte(ctx, 0);
|
|
sha1_process_byte(ctx, 0);
|
|
sha1_process_byte(ctx, 0);
|
|
sha1_process_byte(ctx, 0);
|
|
sha1_process_byte(ctx, (uchar)((bitcount >> 24) & 0xFF));
|
|
sha1_process_byte(ctx, (uchar)((bitcount >> 16) & 0xFF));
|
|
sha1_process_byte(ctx, (uchar)((bitcount >> 8 ) & 0xFF));
|
|
sha1_process_byte(ctx, (uchar)((bitcount >> 0 ) & 0xFF));
|
|
|
|
// memcpy(digest, m_digest, 5 * sizeof(uint32_t));#
|
|
|
|
sha1_result_t result = {0};
|
|
memcpy(result.digest, ctx->digest, sizeof(result.digest));
|
|
return result;
|
|
}
|
|
|
|
str_t sha1Str(arena_t *arena, sha1_t *ctx, const void *buf, usize len) {
|
|
sha1_result_t result = sha1(ctx, buf, len);
|
|
return strFmt(arena, "%08x%08x%08x%08x%08x", result.digest[0], result.digest[1], result.digest[2], result.digest[3], result.digest[4]);
|
|
} |