hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 5aaec08f83d401cbeea4a07fe15929af34a0c7f0
parent 02f24e201c8e7c49e959d77dba92fbc02248905a
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sat,  4 Sep 2021 08:07:59 +0200

crypto::*: use subtypes for hashes

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Mcrypto/blake2b/+test.ha | 13++++++-------
Mcrypto/blake2b/blake2b.ha | 18++++++++----------
Mcrypto/md5/+test.ha | 8+++-----
Mcrypto/md5/md5.ha | 16++++++++--------
Mcrypto/sha1/+test.ha | 13+++++--------
Mcrypto/sha1/sha1.ha | 15+++++----------
Mcrypto/sha256/+test.ha | 14++++++--------
Mcrypto/sha256/sha256.ha | 15+++++----------
Mcrypto/sha512/+test.ha | 33+++++++++++++++------------------
Mcrypto/sha512/sha512.ha | 23++++++++++-------------
Mhare/module/scan.ha | 20++++++++------------
11 files changed, 79 insertions(+), 109 deletions(-)

diff --git a/crypto/blake2b/+test.ha b/crypto/blake2b/+test.ha @@ -14,20 +14,19 @@ use strio; let in = hex::decode(vectors[i].in)!; defer free(in); let blake = blake2b(key, len(out)); - hash::write(blake, in); + hash::write(&blake, in); let sum: []u8 = alloc([], len(out)); defer free(sum); for (let i = 0z; i < len(out); i += 1) { append(sum, 0); }; - hash::finish(blake, sum); + hash::finish(&blake, sum); let out = strio::dynamic(); hex::encode(out, sum)!; assert(strio::string(out) == vectors[i].out); }; let blake = blake2b([], 64); - defer hash::close(blake); const vectors = [ ("", "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce"), ("abc", "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923"), @@ -41,12 +40,12 @@ use strio; for (let i = 0z; i < len(vectors); i += 1) { const vector = vectors[i]; - hash::reset(blake); - hash::write(blake, strings::toutf8(vector.0)); + hash::reset(&blake); + hash::write(&blake, strings::toutf8(vector.0)); static let sum: [64]u8 = [0...]; - assert(len(sum) >= hash::sz(blake)); - hash::sum(blake, sum); + assert(len(sum) >= hash::sz(&blake)); + hash::sum(&blake, sum); let hex = strio::dynamic(); defer io::close(hex); diff --git a/crypto/blake2b/blake2b.ha b/crypto/blake2b/blake2b.ha @@ -32,7 +32,7 @@ const sigma: [12][16]u8 = [ [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], ]; -type digest = struct { +export type digest = struct { hash::hash, h: [8]u64, tlow: u64, @@ -44,8 +44,10 @@ type digest = struct { }; // Creates a [[hash::hash]] which computes a BLAKE2b hash with a given key and a -// given hash size. The size must be between 1 and 64, inclusive. -export fn blake2b(key: []u8, sz: size) *hash::hash = { +// given hash size. The size must be between 1 and 64, inclusive. This hash +// function does not allocate any additional state, so you do not need to call +// [[hash::close]] when you are done with it. +export fn blake2b(key: []u8, sz: size) digest = { assert(1 <= sz); assert(sz <= 64); assert(len(key) <= 64); @@ -53,9 +55,8 @@ export fn blake2b(key: []u8, sz: size) *hash::hash = { h[0] ^= 0x01010000 ^ (len(key) << 8) ^ sz; let keyblock: [BSIZE]u8 = [0...]; keyblock[..len(key)] = key; - return alloc(digest { + return digest { writer = &write, - closer = &close, sum = &sum, reset = &reset, sz = sz, @@ -66,7 +67,8 @@ export fn blake2b(key: []u8, sz: size) *hash::hash = { blocklen = if (len(key) > 0) BSIZE else 0, key = keyblock, keylen = len(key), - }): *hash::hash; + ... + }; }; fn write(st: *io::stream, buf: const []u8) (size | io::error) = { @@ -94,10 +96,6 @@ fn write(st: *io::stream, buf: const []u8) (size | io::error) = { return length; }; -fn close(st: *io::stream) void = { - free(st); -}; - fn sum(h: *hash::hash, buf: []u8) void = { let h = h: *digest; let copy = *h; diff --git a/crypto/md5/+test.ha b/crypto/md5/+test.ha @@ -6,8 +6,6 @@ use io; @test fn md5() void = { let md5 = md5(); - defer hash::close(md5); - const vectors = [ ("", "d41d8cd98f00b204e9800998ecf8427e"), ("abc", "900150983cd24fb0d6963f7d28e17f72"), @@ -22,11 +20,11 @@ use io; for (let i = 0z; i < len(vectors); i += 1) { const vector = vectors[i]; - hash::reset(md5); - hash::write(md5, strings::toutf8(vector.0)); + hash::reset(&md5); + hash::write(&md5, strings::toutf8(vector.0)); let sum: [SIZE]u8 = [0...]; - hash::sum(md5, sum); + hash::sum(&md5, sum); let hex = strio::dynamic(); defer io::close(hex); diff --git a/crypto/md5/md5.ha b/crypto/md5/md5.ha @@ -12,7 +12,7 @@ def init1: u32 = 0xEFCDAB89; def init2: u32 = 0x98BADCFE; def init3: u32 = 0x10325476; -type digest = struct { +export type digest = struct { hash::hash, h: [4]u32, x: [chunk]u8, @@ -24,16 +24,18 @@ type digest = struct { // Note that MD5 is cryptographically broken and should not be used for secure // applications. Where possible, applications are encouraged to use // [[crypto::sha256]] or [[crypto::sha512]] instead. -export fn md5() *hash::hash = { - let md5 = alloc(digest { +// +// This hash function does not allocate any state, so you do not have to call +// [[hash::close]] when you are done with it. +export fn md5() digest = { + let md5 = digest { writer = &write, - closer = &close, sum = &sum, reset = &reset, sz = SIZE, ... - }); - hash::reset(md5); + }; + hash::reset(&md5); return md5; }; @@ -69,8 +71,6 @@ fn write(st: *io::stream, buf: const []u8) (size | io::error) = { return nn; }; -fn close(st: *io::stream) void = free(st); - fn reset(h: *hash::hash) void = { let h = h: *digest; h.h[0] = init0; diff --git a/crypto/sha1/+test.ha b/crypto/sha1/+test.ha @@ -6,8 +6,6 @@ use io; @test fn sha1() void = { let sha = sha1(); - defer hash::close(sha); - const vectors = [ ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"), ("abc", "a9993e364706816aba3e25717850c26c9cd0d89d"), @@ -26,11 +24,11 @@ use io; for (let i = 0z; i < len(vectors); i += 1) { const vector = vectors[i]; - hash::reset(sha); - hash::write(sha, strings::toutf8(vector.0)); + hash::reset(&sha); + hash::write(&sha, strings::toutf8(vector.0)); let sum: [SIZE]u8 = [0...]; - hash::sum(sha, sum); + hash::sum(&sha, sum); let hex = strio::dynamic(); defer io::close(hex); @@ -52,12 +50,11 @@ use io; // const expected = "7789f0c9ef7bfc40d93311143dfbe69e2017f592"; // // let sha = sha1(); -// defer hash::finish(sha); // // for (let i = 0z; i < 16777216; i += 1) -// hash::write(sha, strings::toutf8(input)); +// hash::write(&sha, strings::toutf8(input)); // -// let sum = hash::sum(sha); +// let sum = hash::sum(&sha); // defer free(sum); // // let hex = strio::dynamic(); diff --git a/crypto/sha1/sha1.ha b/crypto/sha1/sha1.ha @@ -15,7 +15,7 @@ def init2: u32 = 0x98BADCFE; def init3: u32 = 0x10325476; def init4: u32 = 0xC3D2E1F0; -type digest = struct { +export type digest = struct { hash::hash, h: [5]u32, x: [chunk]u8, @@ -26,16 +26,15 @@ type digest = struct { // Creates a [[hash::hash]] which computes a SHA-1 hash. Note that this // alogorithm is no longer considered secure. Where possible, applications are // encouraged to use [[crypto::sha256]] or [[crypto::sha512]] instead. -export fn sha1() *hash::hash = { - let sha = alloc(digest { +export fn sha1() digest = { + let sha = digest { writer = &write, - closer = &close, sum = &sum, reset = &reset, sz = SIZE, ... - }); - hash::reset(sha); + }; + hash::reset(&sha); return sha; }; @@ -71,10 +70,6 @@ fn write(st: *io::stream, buf: const []u8) (size | io::error) = { return nn; }; -fn close(st: *io::stream) void = { - free(st); -}; - fn reset(h: *hash::hash) void = { let h = h: *digest; h.h[0] = init0; diff --git a/crypto/sha256/+test.ha b/crypto/sha256/+test.ha @@ -6,8 +6,6 @@ use strio; @test fn sha256() void = { let sha = sha256(); - defer hash::close(sha); - const vectors = [ ("", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"), ("abc", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"), @@ -23,11 +21,11 @@ use strio; for (let i = 0z; i < len(vectors); i += 1) { const vector = vectors[i]; - hash::reset(sha); - hash::write(sha, strings::toutf8(vector.0)); + hash::reset(&sha); + hash::write(&sha, strings::toutf8(vector.0)); let sum: [SIZE]u8 = [0...]; - hash::sum(sha, sum); + hash::sum(&sha, sum); let hex = strio::dynamic(); defer io::close(hex); @@ -46,11 +44,11 @@ use strio; //const input = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"; //const expected = "50e72a0e26442fe2552dc3938ac58658228c0cbfb1d2ca872ae435266fcd055e"; - //hash::reset(sha); + //hash::reset(&sha); //for (let i = 0z; i < 16777216; i += 1) { - // hash::write(sha, strings::toutf8(input)); + // hash::write(&sha, strings::toutf8(input)); //}; - //let sum = hash::sum(sha); + //let sum = hash::sum(&sha); //defer free(sum); //let hex = strio::dynamic(); diff --git a/crypto/sha256/sha256.ha b/crypto/sha256/sha256.ha @@ -31,7 +31,7 @@ const k: [_]u32 = [ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, ]; -type state = struct { +export type state = struct { hash::hash, h: [8]u32, x: [chunk]u8, @@ -40,16 +40,15 @@ type state = struct { }; // Creates a [[hash::hash]] which computes a SHA-256 hash. -export fn sha256() *hash::hash = { - let sha = alloc(state { +export fn sha256() state = { + let sha = state { writer = &write, - closer = &close, sum = &sum, reset = &reset, sz = SIZE, ... - }); - hash::reset(sha); + }; + hash::reset(&sha); return sha; }; @@ -97,10 +96,6 @@ fn write(st: *io::stream, buf: const []u8) (size | io::error) = { return n; }; -fn close(st: *io::stream) void = { - free(st); -}; - fn sum(h: *hash::hash, buf: []u8) void = { let h = h: *state; let copy = *h; diff --git a/crypto/sha512/+test.ha b/crypto/sha512/+test.ha @@ -6,8 +6,6 @@ use io; @test fn sha512() void = { let sha = sha512(); - defer hash::close(sha); - const vectors = [ ("abc", "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"), ("", "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"), @@ -22,11 +20,11 @@ use io; for (let i = 0z; i < len(vectors); i += 1) { const vector = vectors[i]; - hash::reset(sha); - hash::write(sha, strings::toutf8(vector.0)); + hash::reset(&sha); + hash::write(&sha, strings::toutf8(vector.0)); let sum: [SIZE]u8 = [0...]; - hash::sum(sha, sum); + hash::sum(&sha, sum); let hex = strio::dynamic(); defer io::close(hex); @@ -45,20 +43,19 @@ use io; @test fn sha512_224() void = { let sha = sha512_224(); - defer hash::close(sha); - const vectors = [ ("", "6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4"), ("abc", "4634270f707b6a54daae7530460842e20e37ed265ceee9a43e8924aa"), ("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "23fec5bb94d60b23308192640b0c453335d664734fe40e7268674af9") ]; + for (let i = 0z; i < len(vectors); i += 1) { const vector = vectors[i]; - hash::reset(sha); - hash::write(sha, strings::toutf8(vector.0)); + hash::reset(&sha); + hash::write(&sha, strings::toutf8(vector.0)); let sum: [SIZE224]u8 = [0...]; - hash::sum(sha, sum); + hash::sum(&sha, sum); let hex = strio::dynamic(); defer io::close(hex); @@ -76,19 +73,19 @@ use io; @test fn sha512_256() void = { let sha = sha512_256(); - defer hash::close(sha); const vectors = [ ("", "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a"), ("abc", "53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"), ("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "3928e184fb8690f840da3988121d31be65cb9d3ef83ee6146feac861e19b563a"), ]; + for (let i = 0z; i < len(vectors); i += 1) { const vector = vectors[i]; - hash::reset(sha); - hash::write(sha, strings::toutf8(vector.0)); + hash::reset(&sha); + hash::write(&sha, strings::toutf8(vector.0)); let sum: [SIZE256]u8 = [0...]; - hash::sum(sha, sum); + hash::sum(&sha, sum); let hex = strio::dynamic(); defer io::close(hex); @@ -108,19 +105,19 @@ use io; @test fn sha384() void = { let sha = sha384(); - defer hash::close(sha); const vectors = [ ("", "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"), ("abc", "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"), ("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039"), ]; + for (let i = 0z; i < len(vectors); i += 1) { const vector = vectors[i]; - hash::reset(sha); - hash::write(sha, strings::toutf8(vector.0)); + hash::reset(&sha); + hash::write(&sha, strings::toutf8(vector.0)); let sum: [SIZE384]u8 = [0...]; - hash::sum(sha, sum); + hash::sum(&sha, sum); let hex = strio::dynamic(); defer io::close(hex); diff --git a/crypto/sha512/sha512.ha b/crypto/sha512/sha512.ha @@ -56,7 +56,7 @@ def init5_384: u64 = 0x8eb44a8768581511; def init6_384: u64 = 0xdb0c2e0d64f98fa7; def init7_384: u64 = 0x47b5481dbefa4fa4; -type digest = struct { +export type digest = struct { hash::hash, h: [8]u64, x: [chunk]u8, @@ -66,29 +66,28 @@ type digest = struct { }; // Creates a [[hash::hash]] which computes a SHA-512 hash. -export fn sha512() *hash::hash = init(variant::SHA512, SIZE); +export fn sha512() digest = init(variant::SHA512, SIZE); // Creates a [[hash::hash]] which computes a SHA-512/224 hash. -export fn sha512_224() *hash::hash = init(variant::SHA512_224, SIZE224); +export fn sha512_224() digest = init(variant::SHA512_224, SIZE224); // Creates a [[hash::hash]] which computes a SHA-512/256 hash. -export fn sha512_256() *hash::hash = init(variant::SHA512_256, SIZE256); +export fn sha512_256() digest = init(variant::SHA512_256, SIZE256); // Creates a [[hash::hash]] which computes a SHA-384 hash. -export fn sha384() *hash::hash = init(variant::SHA384, SIZE384); +export fn sha384() digest = init(variant::SHA384, SIZE384); // Internal initialization function -fn init(var: variant, sz: size) *hash::hash = { - let sha = alloc(digest { +fn init(var: variant, sz: size) digest = { + let sha = digest { writer = &write, - closer = &close, sum = &sum, reset = &reset, sz = sz, var = var, - }); - - hash::reset(sha); + ... + }; + hash::reset(&sha); return sha; }; @@ -124,8 +123,6 @@ fn write(st: *io::stream, buf: const []u8) (size | io::error) = { return nn; }; -fn close(st: *io::stream) void = free(st); - fn sum(h: *hash::hash, buf: []u8) void = { let d = h: *digest; let copy = *d; diff --git a/hare/module/scan.ha b/hare/module/scan.ha @@ -20,7 +20,6 @@ use fmt; export fn scan(ctx: *context, path: str) (version | error) = { // TODO: Incorporate defines into the hash let sha = sha256::sha256(); - defer hash::close(sha); let found = false; for (let i = 0z; i < len(ctx.tags); i += 1) { if (ctx.tags[i].mode == tag_mode::INCLUSIVE @@ -29,7 +28,7 @@ export fn scan(ctx: *context, path: str) (version | error) = { break; }; }; - hash::write(sha, [if (found) 1 else 0]); + hash::write(&sha, [if (found) 1 else 0]); let iter = match (fs::iter(ctx.fs, path)) { fs::wrongtype => { // Single file case @@ -50,8 +49,8 @@ export fn scan(ctx: *context, path: str) (version | error) = { append(inputs, in); let sumbuf: [sha256::SIZE]u8 = [0...]; - hash::write(sha, in.hash); - hash::sum(sha, sumbuf); + hash::write(&sha, in.hash); + hash::sum(&sha, sumbuf); return version { hash = sumbuf, @@ -67,13 +66,12 @@ export fn scan(ctx: *context, path: str) (version | error) = { basedir = strings::dup(path), ... }; - scan_directory(ctx, &ver, sha, path, iter)?; + scan_directory(ctx, &ver, &sha, path, iter)?; let tmp: [sha256::SIZE]u8 = [0...]; - hash::sum(sha, tmp); + hash::sum(&sha, tmp); ver.hash = alloc([], sha.sz); append(ver.hash, tmp...); - return ver; }; @@ -316,11 +314,9 @@ fn scan_file( let f = fs::open(ctx.fs, path)?; defer io::close(f); let sha = sha256::sha256(); - defer hash::close(sha); - - hash::write(sha, strings::toutf8(path)); + hash::write(&sha, strings::toutf8(path)); - let tee = io::tee(f, sha); + let tee = io::tee(f, &sha); defer io::close(tee); let lexer = lex::init(tee, path); @@ -339,7 +335,7 @@ fn scan_file( io::copy(io::empty, tee)?; // Finish spooling out the file for the SHA let tmp: [sha256::SIZE]u8 = [0...]; - hash::sum(sha, tmp); + hash::sum(&sha, tmp); let checksum: []u8 = alloc([], sha.sz); append(checksum, tmp...);