[OCaml] High Intensity Training Online
1
(** Bcrypt implementation of the {!Hito_app.Password_hash.S} port, over
2
safepass. The one place that names a hashing algorithm. *)
3
4
(* The log2 work factor. safepass defaults to 6, which is far too cheap for a
5
stored password verifier; 12 is the common baseline and makes a verification
6
take on the order of a quarter second, so an offline attack against a leaked
7
verifier pays that cost for every guess. Raising this later is safe: a hash
8
records its own cost, so existing verifiers keep verifying. *)
9
let cost = 12
10
let hash password = Bcrypt.string_of_hash (Bcrypt.hash ~count:cost password)
11
12
(* A stored verifier that does not parse as a bcrypt hash is corrupt storage,
13
not a wrong password. safepass reports it from [verify], not from
14
[hash_of_string]. Refuse the sign-in (fail closed) but say so on stderr, so
15
the corruption is visible rather than read as a typo. *)
16
let verify ~hash password =
17
match Bcrypt.verify password (Bcrypt.hash_of_string hash) with
18
| verified -> verified
19
| exception e ->
20
Printf.eprintf
21
"hito: stored password verifier is not a bcrypt hash: %s\n%!"
22
(Printexc.to_string e);
23
false
24