src/crypto/kdf.bend
bend-collections@1.0.0.0 · 50 lines · 7 definitions
1import Base
2import bend-collections@1.0.0.0/src/crypto/mac.bend as MAC
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17type KdfError is Data:
18 LengthTooLarge{}
19
20def max_length() -> Nat:
21 8160n
22
23def extract(+salt: List<&2, U32>, ikm: List<&2, U32>) -> List<&2, U32>:
24 MAC.sign(salt, ikm)
25
26
27
28
29def blocks(rem: Nat, +prk: List<&2, U32>, +info: List<&2, U32>, prev: List<&2, U32>, +ctr: U32) -> List<&2, U32>:
30 match rem:
31 case 0n:
32 Nil{}
33 case 32n+r:
34 +t = MAC.sign(prk, List.append(&2, U32, prev, List.append(&2, U32, info, [ctr])))
35 List.append(&2, U32, t, blocks(r, prk, info, t, U32.inc(ctr)))
36 case 1n+p:
37 List.take(&2, U32, MAC.sign(prk, List.append(&2, U32, prev, List.append(&2, U32, info, [ctr]))), 1n+p)
38
39def expand_if(+prk: List<&2, U32>, +info: List<&2, U32>, +len: Nat, ok: Bool) -> Result<&2, &2, KdfError, List<&2, U32>>:
40 match ok:
41 case True{}:
42 Done{blocks(len, prk, info, Nil{}, 1)}
43 case False{}:
44 Fail{LengthTooLarge{}}
45
46def expand(+prk: List<&2, U32>, +info: List<&2, U32>, +len: Nat) -> Result<&2, &2, KdfError, List<&2, U32>>:
47 expand_if(prk, info, len, Nat.is_le(len, max_length()))
48
49def hkdf(+salt: List<&2, U32>, ikm: List<&2, U32>, +info: List<&2, U32>, +len: Nat) -> Result<&2, &2, KdfError, List<&2, U32>>:
50 expand(extract(salt, ikm), info, len)