SignatureRFC 9421 HTTP Message Signatures
This module implements RFC 9421 HTTP Message Signatures, enabling cryptographic signing and verification of HTTP request and response messages.
HTTP Message Signatures provide a mechanism to create and verify cryptographic signatures on HTTP messages. The signature covers specific message components (headers, derived values) and metadata (timestamps, key identifiers).
Eio_main.run @@ fun env ->
let clock = Eio.Stdenv.clock env in
(* Create a signing configuration *)
let key = Signature.Key.ed25519
~priv:(Base64.decode_exn "private-key-bytes")
~pub:(Base64.decode_exn "public-key-bytes") in
let config = Signature.config
~key
~keyid:"my-key-id"
~components:[Signature.Component.method_; Signature.Component.authority]
() in
(* Sign headers *)
let ctx = Signature.Context.request ~method_:`GET ~uri:(Uri.of_string "https://example.com/") ~headers in
let signed_headers = Signature.sign ~clock ~config ~context:ctx ~headers |> Result.get_ok in
(* Verify signatures *)
let result = Signature.verify ~clock ~key ~context:ctx ~headers:signed_headers () in
...module Algorithm : sig ... endSignature algorithms per RFC 9421 Section 3.3.
module Component : sig ... endMessage components that can be included in signatures per RFC 9421 Section 2.
module Params : sig ... endSignature parameters per RFC 9421 Section 2.3.
module Key : sig ... endCryptographic key material for signing and verification.
Request context for signature computation. Contains the HTTP method, request URI, and request headers.
Response context for signature computation. Contains the HTTP status code, response headers, and optionally the original request.
module Context : sig ... endContext for resolving message components.
module Content_digest : sig ... endRFC 9530 Content-Digest support.
val config :
key:Key.t ->
?keyid:string ->
?components:Component.t list ->
?tag:string ->
?include_created:bool ->
?label:string ->
unit ->
configconfig ~key ?keyid ?components ?tag ?include_created ?label () creates a signing configuration.
val default_components : Component.t listDefault components to sign: [\@method; \@authority; \@path].
val sign_error_to_string : sign_error -> stringsign_error_to_string err returns a human-readable error message.
val sign :
clock:_ Eio.Time.clock ->
config:config ->
context:Context.t ->
headers:Headers.t ->
(Headers.t, sign_error) resultsign ~clock ~config ~context ~headers signs the message and returns headers with Signature-Input and Signature headers added.
val sign_with_digest :
clock:_ Eio.Time.clock ->
config:config ->
context:Context.t ->
headers:Headers.t ->
body:string ->
digest_algorithm:Content_digest.algorithm ->
(Headers.t, sign_error) resultsign_with_digest ~clock ~config ~context ~headers ~body ~digest_algorithm computes Content-Digest, adds it to headers, and signs. The content-digest component is automatically added to signed components.
type verify_error = [ | `Missing_signature_header| `Missing_signature_input_header| `Invalid_signature_input of string| `Signature_label_not_found of string| `Key_algorithm_mismatch of string| `Missing_public_key| `Component_resolution_error of string| `Signature_mismatch| `Signature_expired| `Required_component_missing of string| `Crypto_error of string ]val verify_error_to_string : verify_error -> stringverify_error_to_string err returns a human-readable error message.
type verify_result = {label : string;keyid : string option;created : Ptime.t option;expires : Ptime.t option;verified_components : Component.t list;}Successful verification result.
val verify :
clock:_ Eio.Time.clock ->
key:Key.t ->
?label:string ->
?max_age:Ptime.Span.t ->
?required_components:Component.t list ->
context:Context.t ->
headers:Headers.t ->
unit ->
(verify_result, verify_error) resultverify ~clock ~key ?label ?max_age ?required_components ~context ~headers verifies a signature on the message.
Time validation per RFC 9421:
expires is present and in the past, verification failscreated is present and in the future (with 60s clock skew allowance), verification failsmax_age is specified and created is older than max_age, verification failsval verify_all :
clock:_ Eio.Time.clock ->
key_resolver:(string -> Key.t option) ->
?max_age:Ptime.Span.t ->
context:Context.t ->
headers:Headers.t ->
unit ->
(verify_result list, verify_error) resultverify_all ~clock ~key_resolver ?max_age ~context ~headers verifies all signatures on a message.