1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
module type S = sig
val expand : prk:string -> ?info:string -> int -> string
end
module Make (H : Digestif.S) : S = struct
let ?salt ikm =
let key = match salt with
| None -> String.make H.digest_size '\x00'
| Some x -> x
in
H.(to_raw_string (hmac_string ~key ikm))
let expand ~prk ?info len =
let info = match info with
| None -> ""
| Some x -> x
in
let t n last =
let nc = String.make 1 (Char.unsafe_chr n) in
H.(to_raw_string (hmac_string ~key:prk (String.concat "" [last ; info ; nc])))
in
let n = succ (len / H.digest_size) in
let rec compute acc count = match count, acc with
| c, xs when c > n -> String.concat "" (List.rev xs)
| c, x::_ -> compute (t c x :: acc) (succ c)
| _, [] -> invalid_arg "can not happen"
in
let buf = compute [""] 1 in
String.sub buf 0 len
end
let ~hash ?salt ikm =
let module H = (val (Digestif.module_of_hash' hash)) in
let module HKDF = Make (H) in
HKDF.extract ?salt ikm
let expand ~hash ~prk ?info len =
let module H = (val (Digestif.module_of_hash' hash)) in
let module HKDF = Make (H) in
HKDF.expand ~prk ?info len