this repo has no description
1let nonce_size = 12
2let tag_size = 16
3let version_size = 1
4let encryption_version = 1
5let key_size = 16
6let overhead = version_size + nonce_size + tag_size
7
8type key = Mirage_crypto.AES.GCM.key
9
10let init_key secret =
11 if String.length secret <> key_size then Error `Invalid_key_length
12 else Ok (Mirage_crypto.AES.GCM.of_secret secret)
13
14let generate_nonce (random : _ Eio.Flow.source) =
15 let buf = Cstruct.create nonce_size in
16 Eio.Flow.read_exact random buf;
17 Cstruct.to_string buf
18
19let encrypt ~key ~random plaintext =
20 let nonce = generate_nonce random in
21 let ciphertext =
22 Mirage_crypto.AES.GCM.authenticate_encrypt ~key ~nonce
23 (Cstruct.to_string plaintext)
24 in
25 let result =
26 Cstruct.create (version_size + nonce_size + String.length ciphertext)
27 in
28 Cstruct.set_uint8 result 0 encryption_version;
29 Cstruct.blit_from_string nonce 0 result version_size nonce_size;
30 Cstruct.blit_from_string ciphertext 0 result
31 (version_size + nonce_size)
32 (String.length ciphertext);
33 result
34
35let pkcs7_unpad data block_size =
36 let len = String.length data in
37 if len = 0 then data
38 else
39 let padding = Char.code data.[len - 1] in
40 if padding > 0 && padding <= block_size && padding <= len then
41 String.sub data 0 (len - padding)
42 else data
43
44let decrypt ~key data =
45 if Cstruct.length data < overhead then Error `Too_short
46 else
47 let version = Cstruct.get_uint8 data 0 in
48 if version > 1 then Error `Unsupported_version
49 else
50 let nonce =
51 Cstruct.to_string (Cstruct.sub data version_size nonce_size)
52 in
53 let ciphertext =
54 Cstruct.to_string
55 (Cstruct.sub data
56 (version_size + nonce_size)
57 (Cstruct.length data - version_size - nonce_size))
58 in
59 match
60 Mirage_crypto.AES.GCM.authenticate_decrypt ~key ~nonce ciphertext
61 with
62 | Some plaintext ->
63 let plaintext =
64 if version = 0 then pkcs7_unpad plaintext 16 else plaintext
65 in
66 Ok (Cstruct.of_string plaintext)
67 | None -> Error `Decryption_failed