hare

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

commit 4473110bc6c07fb5185a1540e12d50db7f8f12f7
parent 39332326aa2b6f5e79cf9fed4e9ab28e6f6e3dd1
Author: Drew DeVault <sir@cmpwn.com>
Date:   Mon, 10 Jan 2022 12:02:31 +0100

crypto: implement derivekey

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

Diffstat:
Mcrypto/authenc.ha | 2++
Acrypto/keyderiv.ha | 46++++++++++++++++++++++++++++++++++++++++++++++
Mscripts/gen-stdlib | 8++++++++
Mstdlib.mk | 34++++++++++++++++++++++++++++++++++
4 files changed, 90 insertions(+), 0 deletions(-)

diff --git a/crypto/authenc.ha b/crypto/authenc.ha @@ -1,3 +1,5 @@ +use errors; + // A secret session key. export type sessionkey = [32]u8; diff --git a/crypto/keyderiv.ha b/crypto/keyderiv.ha @@ -0,0 +1,46 @@ +use errors; +use crypto::argon2; + +// Given a password, derive a key. Given the same password, salt, memory, and +// passes, this function will always produce the same key. This function is +// designed to derive cryptographic keys from user-provided passwords, or to +// verify a password for user logins. +// +// The user provides a buffer for the key to be written to via the 'dest' +// parameter. The minimum supported length for this buffer is 4 bytes, and the +// recommended length is 32 bytes. +// +// The salt parameter should be randomly generated, stored alongside the key, +// and used in subsequent calls to produce the same key. It must be at least 8 +// bytes, but 16 bytes is recommended. Use [[crypto::random]] to generate a +// different salt for each key. +// +// The 'mem' and 'passes' functions are provided to tune the behavior of this +// algorithm. It is designed to be computationally expensive, and you must +// adjust these figures to suit your hardware and use-case. If you provide a u32 +// for 'mem', the algorithm will dynamically allocate that many kilobytes of +// working memory. To allocate this memory yourself, provide a []u64 instead. +// The number of passes controls the amount of time spent generating the key, +// higher numbers take longer. +// +// To identify ideal values for these parameters, start with 100000 for 'mem' +// (100 MiB) and 0 for 'passes'. If it takes too long, reduce the amount of +// memory, and if it does not take long enough, increase the amount of memory. +// If you have reached the maximum amount of memory you are able to use, +// increase passes. +export fn derivekey( + dest: []u8, + salt: []u8, + password: []u8, + mem: (u32 | []u64), + passes: u32, +) (void | errors::nomem) = { + const config = argon2::config { + mem = mem, + parallel = 1, + passes = passes + 3, + version = argon2::VERSION, + ... + }; + return argon2::argon2i(dest, password, salt, &config); +}; diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -185,6 +185,13 @@ compress_zlib() { hash::adler32 io fmt } +crypto() { + gen_srcs crypto \ + authenc.ha \ + keyderiv.ha + gen_ssa crypto errors crypto::argon2 +} + gensrcs_crypto_aes() { gen_srcs crypto::aes \ aes_ct64.ha \ @@ -1095,6 +1102,7 @@ bufio bytes compress::flate compress::zlib +crypto crypto::aes crypto::argon2 crypto::blake2b diff --git a/stdlib.mk b/stdlib.mk @@ -144,6 +144,12 @@ stdlib_deps_any+=$(stdlib_compress_zlib_any) stdlib_compress_zlib_linux=$(stdlib_compress_zlib_any) stdlib_compress_zlib_freebsd=$(stdlib_compress_zlib_any) +# gen_lib crypto (any) +stdlib_crypto_any=$(HARECACHE)/crypto/crypto-any.o +stdlib_deps_any+=$(stdlib_crypto_any) +stdlib_crypto_linux=$(stdlib_crypto_any) +stdlib_crypto_freebsd=$(stdlib_crypto_any) + # gen_lib crypto::aes (any) stdlib_crypto_aes_any=$(HARECACHE)/crypto/aes/crypto_aes-any.o stdlib_deps_any+=$(stdlib_crypto_aes_any) @@ -653,6 +659,17 @@ $(HARECACHE)/compress/zlib/compress_zlib-any.ssa: $(stdlib_compress_zlib_any_src @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Ncompress::zlib \ -t$(HARECACHE)/compress/zlib/compress_zlib.td $(stdlib_compress_zlib_any_srcs) +# crypto (+any) +stdlib_crypto_any_srcs= \ + $(STDLIB)/crypto/authenc.ha \ + $(STDLIB)/crypto/keyderiv.ha + +$(HARECACHE)/crypto/crypto-any.ssa: $(stdlib_crypto_any_srcs) $(stdlib_rt) $(stdlib_errors_$(PLATFORM)) $(stdlib_crypto_argon2_$(PLATFORM)) + @printf 'HAREC \t$@\n' + @mkdir -p $(HARECACHE)/crypto + @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Ncrypto \ + -t$(HARECACHE)/crypto/crypto.td $(stdlib_crypto_any_srcs) + # crypto::aes (+any) stdlib_crypto_aes_any_srcs= \ $(STDLIB)/crypto/aes/aes_ct64.ha @@ -1862,6 +1879,12 @@ testlib_deps_any+=$(testlib_compress_zlib_any) testlib_compress_zlib_linux=$(testlib_compress_zlib_any) testlib_compress_zlib_freebsd=$(testlib_compress_zlib_any) +# gen_lib crypto (any) +testlib_crypto_any=$(TESTCACHE)/crypto/crypto-any.o +testlib_deps_any+=$(testlib_crypto_any) +testlib_crypto_linux=$(testlib_crypto_any) +testlib_crypto_freebsd=$(testlib_crypto_any) + # gen_lib crypto::aes (any) testlib_crypto_aes_any=$(TESTCACHE)/crypto/aes/crypto_aes-any.o testlib_deps_any+=$(testlib_crypto_aes_any) @@ -2372,6 +2395,17 @@ $(TESTCACHE)/compress/zlib/compress_zlib-any.ssa: $(testlib_compress_zlib_any_sr @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ncompress::zlib \ -t$(TESTCACHE)/compress/zlib/compress_zlib.td $(testlib_compress_zlib_any_srcs) +# crypto (+any) +testlib_crypto_any_srcs= \ + $(STDLIB)/crypto/authenc.ha \ + $(STDLIB)/crypto/keyderiv.ha + +$(TESTCACHE)/crypto/crypto-any.ssa: $(testlib_crypto_any_srcs) $(testlib_rt) $(testlib_errors_$(PLATFORM)) $(testlib_crypto_argon2_$(PLATFORM)) + @printf 'HAREC \t$@\n' + @mkdir -p $(TESTCACHE)/crypto + @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ncrypto \ + -t$(TESTCACHE)/crypto/crypto.td $(testlib_crypto_any_srcs) + # crypto::aes (+any) testlib_crypto_aes_any_srcs= \ $(STDLIB)/crypto/aes/aes_ct64.ha \