Added generic HMAC.

This commit is contained in:
Christoffer Lerno
2024-09-28 23:28:11 +02:00
parent cc130e04dd
commit 3b009e0b50
4 changed files with 86 additions and 8 deletions

55
lib/std/hash/hmac.c3 Normal file
View File

@@ -0,0 +1,55 @@
module std::hash::hmac(<HashAlg, HASH_BYTES, BLOCK_BYTES>);
struct Hmac
{
HashAlg a, b;
}
fn char[HASH_BYTES] hash(char[] key, char[] message)
{
Hmac hmac @noinit;
hmac.init(key);
hmac.update(message);
return hmac.final();
}
fn void Hmac.init(&self, char[] key)
{
char[BLOCK_BYTES] buffer;
if (key.len > BLOCK_BYTES)
{
self.a.init();
self.a.update(key);
buffer[:HASH_BYTES] = self.a.final()[..];
}
else
{
buffer[:key.len] = key[..];
}
foreach (&b : buffer) *b ^= IPAD;
self.a.init();
self.a.update(&buffer);
foreach (&b : buffer) *b ^= IPAD ^ OPAD;
self.b.init();
self.b.update(&buffer);
buffer = {};
}
fn void Hmac.update(&self, char[] data)
{
self.a.update(data);
}
fn char[HASH_BYTES] Hmac.final(&self)
{
self.b.update(&&self.a.final());
return self.b.final();
}
const IPAD @private = 0x36;
const OPAD @private = 0x5C;

View File

@@ -1,6 +1,10 @@
module std::hash::md5;
import std::hash::hmac;
import std::bits;
const BLOCK_BYTES = 64;
const HASH_BYTES = 16;
struct Md5
{
uint lo, hi;
@@ -9,7 +13,10 @@ struct Md5
uint[16] block;
}
fn char[16] hash(char[] data)
def HmacMd5 = Hmac(<Md5, HASH_BYTES, BLOCK_BYTES>);
def hmac = hmac::hash(<Md5, HASH_BYTES, BLOCK_BYTES>);
fn char[HASH_BYTES] hash(char[] data)
{
Md5 md5;
md5.init();
@@ -58,7 +65,7 @@ fn void Md5.update(&ctx, char[] data)
ctx.buffer[:data.len] = data[..];
}
fn char[16] Md5.final(&ctx)
fn char[HASH_BYTES] Md5.final(&ctx)
{
usz used = (usz)ctx.lo & 0x3f;
ctx.buffer[used++] = 0x80;

View File

@@ -5,13 +5,28 @@
// Implementation was off Steve Reid's SHA-1 C implementation
module std::hash::sha1;
import std::hash::hmac;
import std::bits;
const BLOCK_BYTES = 64;
const HASH_BYTES = 20;
struct Sha1
{
uint[5] state;
uint[2] count;
char[64] buffer;
char[BLOCK_BYTES] buffer;
}
def HmacSha1 = Hmac(<Sha1, HASH_BYTES, BLOCK_BYTES>);
def hmac = hmac::hash(<Sha1, HASH_BYTES, BLOCK_BYTES>);
fn char[HASH_BYTES] hash(char[] data)
{
Sha1 sha1 @noinit;
sha1.init();
sha1.update(data);
return sha1.final();
}
fn void Sha1.init(&self)
@@ -55,7 +70,7 @@ fn void Sha1.update(&self, char[] data)
}
fn char[20] Sha1.final(&self)
fn char[HASH_BYTES] Sha1.final(&self)
{
char[8] finalcount;
for (uint i = 0; i < 8; i++)
@@ -69,21 +84,21 @@ fn char[20] Sha1.final(&self)
}
self.update(&finalcount);
char[20] digest;
for (uint i = 0; i < 20; i++)
char[HASH_BYTES] digest;
for (uint i = 0; i < HASH_BYTES; i++)
{
digest[i] = (char)((self.state[i >> 2] >> ((3 - (i & 3)) * 8)) & 0xFF);
}
// Clear mem
mem::clear(self, Sha1.sizeof);
*self = {};
finalcount = {};
return digest;
}
union Long16 @local
{
char[64] c;
char[BLOCK_BYTES] c;
uint[16] l;
}