mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
257 lines
6.3 KiB
Plaintext
257 lines
6.3 KiB
Plaintext
// Copyright (c) 2021 Christoffer Lerno. All rights reserved.
|
|
// Use of this source code is governed by the MIT license
|
|
// a copy of which can be found in the LICENSE_STDLIB file.
|
|
//
|
|
// 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[BLOCK_BYTES] buffer;
|
|
}
|
|
|
|
def HmacSha1 = Hmac<[Sha1, HASH_BYTES, BLOCK_BYTES]>;
|
|
def hmac = hmac::hash<[Sha1, HASH_BYTES, BLOCK_BYTES]>;
|
|
def pbkdf2 = hmac::pbkdf2<[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)
|
|
{
|
|
// SHA1 initialization constants
|
|
*self = {
|
|
.state = {
|
|
0x67452301,
|
|
0xEFCDAB89,
|
|
0x98BADCFE,
|
|
0x10325476,
|
|
0xC3D2E1F0
|
|
}
|
|
};
|
|
}
|
|
|
|
<*
|
|
@param [in] data
|
|
@require data.len <= uint.max
|
|
*>
|
|
fn void Sha1.update(&self, char[] data)
|
|
{
|
|
uint j = self.count[0];
|
|
uint len = data.len;
|
|
if ((self.count[0] += len << 3) < j) self.count[1]++;
|
|
self.count[1] += len >> 29;
|
|
j = (j >> 3) & 63;
|
|
uint i;
|
|
if (j + len > 63)
|
|
{
|
|
i = 64 - j;
|
|
self.buffer[j..] = data[:i];
|
|
sha1_transform(&self.state, &self.buffer);
|
|
for (; i + 63 < len; i += 64)
|
|
{
|
|
sha1_transform(&self.state, &data[i]);
|
|
}
|
|
j = 0;
|
|
}
|
|
self.buffer[j:len - i] = data[i..];
|
|
}
|
|
|
|
|
|
fn char[HASH_BYTES] Sha1.final(&self)
|
|
{
|
|
char[8] finalcount;
|
|
for (uint i = 0; i < 8; i++)
|
|
{
|
|
finalcount[i] = (char)((self.count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 0xFF);
|
|
}
|
|
self.update(char[] { 0o200 });
|
|
while ((self.count[0] & 504) != 448)
|
|
{
|
|
self.update(char[] { 0 });
|
|
}
|
|
|
|
self.update(&finalcount);
|
|
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
|
|
*self = {};
|
|
finalcount = {};
|
|
return digest;
|
|
}
|
|
|
|
union Long16 @local
|
|
{
|
|
char[BLOCK_BYTES] c;
|
|
uint[16] l;
|
|
}
|
|
|
|
macro blk(Long16* block, i) @local
|
|
{
|
|
return (block.l[i & 15] = (block.l[(i + 13) & 15] ^ block.l[(i + 8) & 15]
|
|
^ block.l[(i + 2) & 15] ^ block.l[i & 15]).rotl(1));
|
|
}
|
|
|
|
macro blk0(Long16* block, i) @local
|
|
{
|
|
$if env::BIG_ENDIAN:
|
|
return block.l[i];
|
|
$else
|
|
return block.l[i] = (block.l[i].rotl(24) & 0xFF00FF00)
|
|
| (block.l[i].rotl(8) & 0x00FF00FF);
|
|
$endif
|
|
}
|
|
|
|
macro r0(Long16* block, uint v, uint* wref, uint x, uint y, uint* z, uint i) @local
|
|
{
|
|
var w = *wref;
|
|
*z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + v.rotl(5);
|
|
*wref = w.rotl(30);
|
|
}
|
|
|
|
macro r1(Long16* block, uint v, uint* wref, uint x, uint y, uint* z, uint i) @local
|
|
{
|
|
var w = *wref;
|
|
*z += ((w & (x ^ y)) ^ y) + blk(block, i) + 0x5A827999 + v.rotl(5);
|
|
*wref = w.rotl(30);
|
|
}
|
|
|
|
macro r2(Long16* block, uint v, uint* wref, uint x, uint y, uint* z, uint i) @local
|
|
{
|
|
var w = *wref;
|
|
*z += (w ^ x ^ y) + blk(block, i) + 0x6ED9EBA1 + v.rotl(5);
|
|
*wref = w.rotl(30);
|
|
}
|
|
|
|
macro r3(Long16* block, uint v, uint* wref, uint x, uint y, uint* z, uint i) @local
|
|
{
|
|
var w = *wref;
|
|
*z += (((w | x) & y) | (w & x)) + blk(block, i) + 0x8F1BBCDC + v.rotl(5);
|
|
*wref = w.rotl(30);
|
|
}
|
|
|
|
macro r4(Long16* block, uint v, uint* wref, uint x, uint y, uint* z, uint i) @local
|
|
{
|
|
var w = *wref;
|
|
*z += (w ^ x ^ y) + blk(block, i) + 0xCA62C1D6 + v.rotl(5);
|
|
*wref = w.rotl(30);
|
|
}
|
|
|
|
<*
|
|
@param [&inout] state
|
|
@param [&in] buffer
|
|
*>
|
|
fn void sha1_transform(uint[5]* state, char* buffer) @local
|
|
{
|
|
Long16 block;
|
|
block.c[..] = buffer[:64];
|
|
uint a = (*state)[0];
|
|
uint b = (*state)[1];
|
|
uint c = (*state)[2];
|
|
uint d = (*state)[3];
|
|
uint e = (*state)[4];
|
|
r0(&block, a, &b, c, d, &e, 0);
|
|
r0(&block, e, &a, b, c, &d, 1);
|
|
r0(&block, d, &e, a, b, &c, 2);
|
|
r0(&block, c, &d, e, a, &b, 3);
|
|
r0(&block, b, &c, d, e, &a, 4);
|
|
r0(&block, a, &b, c, d, &e, 5);
|
|
r0(&block, e, &a, b, c, &d, 6);
|
|
r0(&block, d, &e, a, b, &c, 7);
|
|
r0(&block, c, &d, e, a, &b, 8);
|
|
r0(&block, b, &c, d, e, &a, 9);
|
|
r0(&block, a, &b, c, d, &e, 10);
|
|
r0(&block, e, &a, b, c, &d, 11);
|
|
r0(&block, d, &e, a, b, &c, 12);
|
|
r0(&block, c, &d, e, a, &b, 13);
|
|
r0(&block, b, &c, d, e, &a, 14);
|
|
r0(&block, a, &b, c, d, &e, 15);
|
|
r1(&block, e, &a, b, c, &d, 16);
|
|
r1(&block, d, &e, a, b, &c, 17);
|
|
r1(&block, c, &d, e, a, &b, 18);
|
|
r1(&block, b, &c, d, e, &a, 19);
|
|
r2(&block, a, &b, c, d, &e, 20);
|
|
r2(&block, e, &a, b, c, &d, 21);
|
|
r2(&block, d, &e, a, b, &c, 22);
|
|
r2(&block, c, &d, e, a, &b, 23);
|
|
r2(&block, b, &c, d, e, &a, 24);
|
|
r2(&block, a, &b, c, d, &e, 25);
|
|
r2(&block, e, &a, b, c, &d, 26);
|
|
r2(&block, d, &e, a, b, &c, 27);
|
|
r2(&block, c, &d, e, a, &b, 28);
|
|
r2(&block, b, &c, d, e, &a, 29);
|
|
r2(&block, a, &b, c, d, &e, 30);
|
|
r2(&block, e, &a, b, c, &d, 31);
|
|
r2(&block, d, &e, a, b, &c, 32);
|
|
r2(&block, c, &d, e, a, &b, 33);
|
|
r2(&block, b, &c, d, e, &a, 34);
|
|
r2(&block, a, &b, c, d, &e, 35);
|
|
r2(&block, e, &a, b, c, &d, 36);
|
|
r2(&block, d, &e, a, b, &c, 37);
|
|
r2(&block, c, &d, e, a, &b, 38);
|
|
r2(&block, b, &c, d, e, &a, 39);
|
|
r3(&block, a, &b, c, d, &e, 40);
|
|
r3(&block, e, &a, b, c, &d, 41);
|
|
r3(&block, d, &e, a, b, &c, 42);
|
|
r3(&block, c, &d, e, a, &b, 43);
|
|
r3(&block, b, &c, d, e, &a, 44);
|
|
r3(&block, a, &b, c, d, &e, 45);
|
|
r3(&block, e, &a, b, c, &d, 46);
|
|
r3(&block, d, &e, a, b, &c, 47);
|
|
r3(&block, c, &d, e, a, &b, 48);
|
|
r3(&block, b, &c, d, e, &a, 49);
|
|
r3(&block, a, &b, c, d, &e, 50);
|
|
r3(&block, e, &a, b, c, &d, 51);
|
|
r3(&block, d, &e, a, b, &c, 52);
|
|
r3(&block, c, &d, e, a, &b, 53);
|
|
r3(&block, b, &c, d, e, &a, 54);
|
|
r3(&block, a, &b, c, d, &e, 55);
|
|
r3(&block, e, &a, b, c, &d, 56);
|
|
r3(&block, d, &e, a, b, &c, 57);
|
|
r3(&block, c, &d, e, a, &b, 58);
|
|
r3(&block, b, &c, d, e, &a, 59);
|
|
r4(&block, a, &b, c, d, &e, 60);
|
|
r4(&block, e, &a, b, c, &d, 61);
|
|
r4(&block, d, &e, a, b, &c, 62);
|
|
r4(&block, c, &d, e, a, &b, 63);
|
|
r4(&block, b, &c, d, e, &a, 64);
|
|
r4(&block, a, &b, c, d, &e, 65);
|
|
r4(&block, e, &a, b, c, &d, 66);
|
|
r4(&block, d, &e, a, b, &c, 67);
|
|
r4(&block, c, &d, e, a, &b, 68);
|
|
r4(&block, b, &c, d, e, &a, 69);
|
|
r4(&block, a, &b, c, d, &e, 70);
|
|
r4(&block, e, &a, b, c, &d, 71);
|
|
r4(&block, d, &e, a, b, &c, 72);
|
|
r4(&block, c, &d, e, a, &b, 73);
|
|
r4(&block, b, &c, d, e, &a, 74);
|
|
r4(&block, a, &b, c, d, &e, 75);
|
|
r4(&block, e, &a, b, c, &d, 76);
|
|
r4(&block, d, &e, a, b, &c, 77);
|
|
r4(&block, c, &d, e, a, &b, 78);
|
|
r4(&block, b, &c, d, e, &a, 79);
|
|
(*state)[0] += a;
|
|
(*state)[1] += b;
|
|
(*state)[2] += c;
|
|
(*state)[3] += d;
|
|
(*state)[4] += e;
|
|
a = b = c = d = e = 0;
|
|
block = {};
|
|
} |