mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Sha1.
This commit is contained in:
@@ -74,14 +74,14 @@ fn void*! SimpleHeapAllocator._realloc(SimpleHeapAllocator* this, void* old_poin
|
||||
return new;
|
||||
}
|
||||
|
||||
fn void*! SimpleHeapAllocator._calloc(SimpleHeapAllocator* this, usz bytes) @private
|
||||
fn void*! SimpleHeapAllocator._calloc(SimpleHeapAllocator* this, usz bytes) @local
|
||||
{
|
||||
void* data = this._alloc(bytes)?;
|
||||
mem::clear(data, bytes, DEFAULT_MEM_ALIGNMENT);
|
||||
return data;
|
||||
}
|
||||
|
||||
fn void*! SimpleHeapAllocator._alloc(SimpleHeapAllocator* this, usz bytes) @private
|
||||
fn void*! SimpleHeapAllocator._alloc(SimpleHeapAllocator* this, usz bytes) @local
|
||||
{
|
||||
usz aligned_bytes = mem::aligned_offset(bytes, DEFAULT_MEM_ALIGNMENT);
|
||||
if (!this.free_list)
|
||||
@@ -130,7 +130,7 @@ fn void*! SimpleHeapAllocator._alloc(SimpleHeapAllocator* this, usz bytes) @priv
|
||||
return this.alloc(aligned_bytes);
|
||||
}
|
||||
|
||||
fn void! SimpleHeapAllocator.add_block(SimpleHeapAllocator* this, usz aligned_bytes) @private
|
||||
fn void! SimpleHeapAllocator.add_block(SimpleHeapAllocator* this, usz aligned_bytes) @local
|
||||
{
|
||||
assert(mem::aligned_offset(aligned_bytes, DEFAULT_MEM_ALIGNMENT) == aligned_bytes);
|
||||
char[] result = this.alloc_fn(aligned_bytes + Header.sizeof)?;
|
||||
@@ -141,7 +141,7 @@ fn void! SimpleHeapAllocator.add_block(SimpleHeapAllocator* this, usz aligned_by
|
||||
}
|
||||
|
||||
|
||||
fn void SimpleHeapAllocator._free(SimpleHeapAllocator* this, void* ptr) @private
|
||||
fn void SimpleHeapAllocator._free(SimpleHeapAllocator* this, void* ptr) @local
|
||||
{
|
||||
// Empty ptr -> do nothing.
|
||||
if (!ptr) return;
|
||||
|
||||
@@ -6,7 +6,7 @@ typedef DynStr = VarString;
|
||||
typedef DynString = VarString;
|
||||
typedef DString = VarString;
|
||||
typedef VString = VarString;
|
||||
|
||||
typedef Text = VarString;
|
||||
|
||||
const usz MIN_CAPACITY = 16;
|
||||
|
||||
|
||||
237
lib/std/hash/sha1.c3
Normal file
237
lib/std/hash/sha1.c3
Normal file
@@ -0,0 +1,237 @@
|
||||
// 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::bits;
|
||||
|
||||
struct Sha1
|
||||
{
|
||||
uint[5] state;
|
||||
uint[2] count;
|
||||
char[64] buffer;
|
||||
}
|
||||
|
||||
fn void Sha1.init(Sha1* this)
|
||||
{
|
||||
// SHA1 initialization constants
|
||||
*this = {
|
||||
.state = {
|
||||
0x67452301,
|
||||
0xEFCDAB89,
|
||||
0x98BADCFE,
|
||||
0x10325476,
|
||||
0xC3D2E1F0
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param [&inout] this
|
||||
* @param [in] data
|
||||
* @require data.len <= uint.max
|
||||
**/
|
||||
fn void Sha1.update(Sha1* this, char[] data)
|
||||
{
|
||||
uint j = this.count[0];
|
||||
uint len = data.len;
|
||||
if ((this.count[0] += len << 3) < j) this.count[1]++;
|
||||
this.count[1] += len >> 29;
|
||||
j = (j >> 3) & 63;
|
||||
uint i;
|
||||
if (j + len > 63)
|
||||
{
|
||||
i = 64 - j;
|
||||
this.buffer[j..] = data[:i];
|
||||
sha1_transform(&this.state, &this.buffer);
|
||||
for (; i + 63 < len; i += 64)
|
||||
{
|
||||
sha1_transform(&this.state, &data[i]);
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
this.buffer[j:len - i] = data[i..];
|
||||
}
|
||||
|
||||
|
||||
fn char[20] Sha1.final(Sha1* this)
|
||||
{
|
||||
char[8] finalcount;
|
||||
for (uint i = 0; i < 8; i++)
|
||||
{
|
||||
finalcount[i] = (char)((this.count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 0xFF);
|
||||
}
|
||||
this.update(char[] { 0o200 });
|
||||
while ((this.count[0] & 504) != 448)
|
||||
{
|
||||
this.update(char[] { 0 });
|
||||
}
|
||||
|
||||
this.update(&finalcount);
|
||||
char[20] digest;
|
||||
for (uint i = 0; i < 20; i++)
|
||||
{
|
||||
digest[i] = (char)((this.state[i >> 2] >> ((3 - (i & 3)) * 8)) & 0xFF);
|
||||
}
|
||||
|
||||
// Clear mem
|
||||
mem::clear(this, Sha1.sizeof);
|
||||
finalcount = {};
|
||||
return digest;
|
||||
}
|
||||
|
||||
union Long16 @local
|
||||
{
|
||||
char[64] c;
|
||||
uint[16] l;
|
||||
}
|
||||
|
||||
macro @blk(&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(&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(&block, v, &w, x, y, &z, i) @local
|
||||
{
|
||||
z += ((w & (x ^ y)) ^ y) + @blk0(block, i) + 0x5A827999 + v.rotl(5);
|
||||
w = w.rotl(30);
|
||||
}
|
||||
|
||||
macro @r1(&block, v, &w, x, y, &z, i) @local
|
||||
{
|
||||
z += ((w & (x ^ y)) ^ y) + @blk(block, i) + 0x5A827999 + v.rotl(5);
|
||||
w = w.rotl(30);
|
||||
}
|
||||
|
||||
macro @r2(&block, v, &w, x, y, &z, i) @local
|
||||
{
|
||||
z += (w ^ x ^ y) + @blk(block, i) + 0x6ED9EBA1 + v.rotl(5);
|
||||
w = w.rotl(30);
|
||||
}
|
||||
|
||||
macro @r3(&block, v, &w, x, y, &z, i) @local
|
||||
{
|
||||
z += (((w | x) &y) | (w & x)) + @blk(block, i) + 0x8F1BBCDC + v.rotl(5);
|
||||
w = w.rotl(30);
|
||||
}
|
||||
|
||||
macro @r4(&block, v, &w, x, y, &z, i) @local
|
||||
{
|
||||
z += (w ^ x ^ y) + @blk(block, i) + 0xCA62C1D6 + v.rotl(5);
|
||||
w = w.rotl(30);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param [&inout] state
|
||||
* @param [&in] buffer
|
||||
**/
|
||||
fn void sha1_transform(uint* 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;
|
||||
buffer[:64] = 0;
|
||||
}
|
||||
30
test/unit/stdlib/hash/sha1.c3
Normal file
30
test/unit/stdlib/hash/sha1.c3
Normal file
@@ -0,0 +1,30 @@
|
||||
module std::hash::sha1_test @test;
|
||||
import std::hash::sha1;
|
||||
|
||||
fn void test_sha1_abc()
|
||||
{
|
||||
Sha1 sha;
|
||||
sha.init();
|
||||
sha.update("abc");
|
||||
assert(sha.final() == x"A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D");
|
||||
}
|
||||
|
||||
fn void test_sha1_longer()
|
||||
{
|
||||
Sha1 sha;
|
||||
sha.init();
|
||||
sha.update("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
|
||||
assert(sha.final() == x"84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1");
|
||||
}
|
||||
|
||||
fn void test_sha1_million_a()
|
||||
{
|
||||
Sha1 sha;
|
||||
sha.init();
|
||||
const int COUNT = 1_000_000;
|
||||
for (int i = 0; i < COUNT / 10; i++)
|
||||
{
|
||||
sha.update("aaaaaaaaaa");
|
||||
}
|
||||
assert(sha.final() == x"34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F");
|
||||
}
|
||||
Reference in New Issue
Block a user