crypto.bend
bend-kit-crypto@0.1.1.0 · 49 lines · 0 definitions
1# Hashes, HMAC, HKDF, and secure random bytes through OpenSSL 3 libcrypto. Source: https://github.com/paymog/bend-kit/tree/main/crypto
2import Base
3
4# Bytes travel as (len, words): len octets, four to a U32 word, low byte first, as Wire.recv.words gives them.
5# The libcrypto effects fail with ENOENT when libcrypto.3 does not load; set BEND_LIBCRYPTO to its path.
6
7# alg is an OpenSSL digest name, such as "SHA256" or "SHA3-256". Fails with EINVAL for an unknown name.
8def digest.words(alg: String, len: U32, words: Array<U32>) ->
9 IO(Result<&1, &1, U32 & String, U32 & Array<U32>>):
10 import "./effs/crypto.c"
11 import "./effs/crypto.js"
12
13def sha256.words(len: U32, words: Array<U32>) -> IO(Result<&1, &1, U32 & String, U32 & Array<U32>>):
14 digest.words("SHA256", len, words)
15
16def sha512.words(len: U32, words: Array<U32>) -> IO(Result<&1, &1, U32 & String, U32 & Array<U32>>):
17 digest.words("SHA512", len, words)
18
19# Legacy: SHA-1 is broken for collisions. Use it only where a protocol needs it, such as the WebSocket handshake.
20def sha1.words(len: U32, words: Array<U32>) -> IO(Result<&1, &1, U32 & String, U32 & Array<U32>>):
21 digest.words("SHA1", len, words)
22
23# HMAC (RFC 2104) of data under key, with the digest alg.
24def hmac.words(alg: String, klen: U32, key: Array<U32>, dlen: U32, data: Array<U32>) ->
25 IO(Result<&1, &1, U32 & String, U32 & Array<U32>>):
26 import "./effs/crypto.c"
27 import "./effs/crypto.js"
28
29# HKDF (RFC 5869): n octets from ikm, salt, and info. Fails with EINVAL when n is 0 or more than 255 digest lengths.
30def hkdf.words(alg: String, slen: U32, salt: Array<U32>, klen: U32, ikm: Array<U32>, ilen: U32, info: Array<U32>, n: U32) ->
31 IO(Result<&1, &1, U32 & String, U32 & Array<U32>>):
32 import "./effs/crypto.c"
33 import "./effs/crypto.js"
34
35# PBKDF2 (RFC 8018 §5.2) with HMAC over alg: n octets from pass and salt. Fails with EINVAL when iters or n is 0.
36def pbkdf2.words(alg: String, plen: U32, pass: Array<U32>, slen: U32, salt: Array<U32>, iters: U32, n: U32) ->
37 IO(Result<&1, &1, U32 & String, U32 & Array<U32>>):
38 import "./effs/crypto.c"
39 import "./effs/crypto.js"
40
41# n octets from the OS secure random source (getentropy, crypto.getRandomValues). Needs no libcrypto.
42def random.words(n: U32) -> IO(Result<&1, &1, U32 & String, U32 & Array<U32>>):
43 import "./effs/crypto.c"
44 import "./effs/crypto.js"
45
46# Equal octets, in time that depends only on the lengths. Use it to compare MACs.
47def eq.ct.words(alen: U32, a: Array<U32>, blen: U32, b: Array<U32>) -> IO(Bool):
48 import "./effs/crypto.c"
49 import "./effs/crypto.js"