let nonce_size = 12 let tag_size = 16 let overhead = nonce_size + tag_size type key = Mirage_crypto.AES.GCM.key let init_key secret = if String.length secret <> 32 then Error `Invalid_key_length else Ok (Mirage_crypto.AES.GCM.of_secret secret) let generate_nonce (random : _ Eio.Flow.source) = let buf = Cstruct.create nonce_size in Eio.Flow.read_exact random buf; Cstruct.to_string buf let encrypt ~key ~random plaintext = let nonce = generate_nonce random in let ciphertext = Mirage_crypto.AES.GCM.authenticate_encrypt ~key ~nonce (Cstruct.to_string plaintext) in let result = Cstruct.create (nonce_size + String.length ciphertext) in Cstruct.blit_from_string nonce 0 result 0 nonce_size; Cstruct.blit_from_string ciphertext 0 result nonce_size (String.length ciphertext); result let decrypt ~key data = if Cstruct.length data < overhead then Error `Too_short else let nonce = Cstruct.to_string (Cstruct.sub data 0 nonce_size) in let ciphertext = Cstruct.to_string (Cstruct.sub data nonce_size (Cstruct.length data - nonce_size)) in match Mirage_crypto.AES.GCM.authenticate_decrypt ~key ~nonce ciphertext with | Some plaintext -> Ok (Cstruct.of_string plaintext) | None -> Error `Decryption_failed