CSRF protection using HMAC-signed state tokens (RFC 5869, RFC 2104)
1(** Fuzz tests for CSRF module *)
2
3open Alcobar
4
5let () = Crypto_rng_unix.use_default ()
6
7(** Roundtrip: sign then verify should return original state *)
8let test_roundtrip secret state =
9 if String.length secret = 0 then bad_test ()
10 else
11 let signed = Csrf.sign_state ~secret state in
12 match Csrf.verify_state ~secret signed with
13 | Some recovered -> check_eq ~pp:Format.pp_print_string state recovered
14 | None -> fail "verification failed for valid signed state"
15
16(** Wrong secret should never verify *)
17let test_wrong_secret secret1 secret2 state =
18 if String.length secret1 = 0 || String.length secret2 = 0 || secret1 = secret2
19 then bad_test ()
20 else
21 let signed = Csrf.sign_state ~secret:secret1 state in
22 match Csrf.verify_state ~secret:secret2 signed with
23 | None -> ()
24 | Some _ -> fail "wrong secret should not verify"
25
26(** Tampered signature should never verify *)
27let test_tampered_signature secret state =
28 if String.length secret = 0 then bad_test ()
29 else
30 let signed = Csrf.sign_state ~secret state in
31 let tampered =
32 let len = String.length signed in
33 if len > 0 then (
34 let b = Bytes.of_string signed in
35 let last = Char.code (Bytes.get b (len - 1)) in
36 Bytes.set b (len - 1) (Char.chr (last lxor 1));
37 Bytes.to_string b)
38 else signed
39 in
40 match Csrf.verify_state ~secret tampered with
41 | None -> ()
42 | Some _ -> fail "tampered signature should not verify"
43
44(** Malformed inputs should never crash *)
45let test_malformed secret input =
46 if String.length secret = 0 then bad_test ()
47 else
48 let _ = Csrf.verify_state ~secret input in
49 ()
50
51let suite =
52 ( "csrf",
53 [
54 test_case "sign/verify roundtrip" [ bytes; bytes ] test_roundtrip;
55 test_case "wrong secret rejects" [ bytes; bytes; bytes ] test_wrong_secret;
56 test_case "tampered signature rejects" [ bytes; bytes ]
57 test_tampered_signature;
58 test_case "malformed input doesn't crash" [ bytes; bytes ] test_malformed;
59 ] )