#include "naut/hash.h" #include static inline uint32_t rol(uint32_t x, int n) { return (x << n) | (x >> (32 - n)); } static void sha1_block(uint32_t h[5], const uint8_t *p, size_t nblocks) { for (size_t b = 0; b < nblocks; b++, p += 64) { uint32_t w[80]; for (int i = 0; i < 16; i++) w[i] = ((uint32_t)p[i*4] << 24) | ((uint32_t)p[i*4+1] << 16) | ((uint32_t)p[i*4+2] << 8) | (uint32_t)p[i*4+3]; for (int i = 16; i < 80; i++) w[i] = rol(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1); uint32_t a = h[0], bb = h[1], c = h[2], d = h[3], e = h[4]; for (int i = 0; i < 80; i++) { uint32_t f, k; if (i < 20) { f = (bb & c) | (~bb & d); k = 0x5A827999; } else if (i < 40) { f = bb ^ c ^ d; k = 0x6ED9EBA1; } else if (i < 60) { f = (bb & c) | (bb & d) | (c & d); k = 0x8F1BBCDC; } else { f = bb ^ c ^ d; k = 0xCA62C1D6; } uint32_t t = rol(a, 5) + f + e + k + w[i]; e = d; d = c; c = rol(bb, 30); bb = a; a = t; } h[0] += a; h[1] += bb; h[2] += c; h[3] += d; h[4] += e; } } void naut_sha1_init(naut_sha1_ctx *c) { c->h[0] = 0x67452301; c->h[1] = 0xEFCDAB89; c->h[2] = 0x98BADCFE; c->h[3] = 0x10325476; c->h[4] = 0xC3D2E1F0; c->len = 0; c->used = 0; } void naut_sha1_update(naut_sha1_ctx *c, const void *data, size_t len) { const uint8_t *p = data; c->len += len; if (c->used) { size_t need = 64 - c->used; size_t take = len < need ? len : need; memcpy(c->block + c->used, p, take); c->used += take; p += take; len -= take; if (c->used == 64) { sha1_block(c->h, c->block, 1); c->used = 0; } } if (len >= 64) { size_t nb = len / 64; sha1_block(c->h, p, nb); p += nb * 64; len -= nb * 64; } if (len) { memcpy(c->block, p, len); c->used = len; } } void naut_sha1_final(naut_sha1_ctx *c, uint8_t out[NAUT_SHA1_LEN]) { uint64_t bits = c->len * 8; uint8_t pad = 0x80; naut_sha1_update(c, &pad, 1); uint8_t zero = 0; while (c->used != 56) naut_sha1_update(c, &zero, 1); uint8_t lenbe[8]; for (int i = 0; i < 8; i++) lenbe[i] = (uint8_t)(bits >> (56 - i*8)); naut_sha1_update(c, lenbe, 8); for (int i = 0; i < 5; i++) { out[i*4] = (uint8_t)(c->h[i] >> 24); out[i*4+1] = (uint8_t)(c->h[i] >> 16); out[i*4+2] = (uint8_t)(c->h[i] >> 8); out[i*4+3] = (uint8_t)(c->h[i]); } } void naut_sha1(const void *data, size_t len, uint8_t out[NAUT_SHA1_LEN]) { naut_sha1_ctx c; naut_sha1_init(&c); naut_sha1_update(&c, data, len); naut_sha1_final(&c, out); }