colla/sha1.c
2024-11-29 16:10:48 +01:00

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]);
}