http_message_signatures/verifier

Public verification API.

Two-step by design: a real verifier needs to inspect keyid (via parse) before it can even look up which public key to verify against, so a single monolithic verify can’t model that.

Types

pub type VerifyError {
  SignatureLabelNotFound
  SignatureInputParseError
  SignatureParseError
  MalformedSignatureParams
  UnsupportedAlgorithm(String)
  ComponentError(component.ComponentError)
  MissingRequiredComponent(component.ComponentIdentifier)
  SignatureExpired
  SignatureTooOld
  InvalidSignature
}

Constructors

  • SignatureLabelNotFound
  • SignatureInputParseError
  • SignatureParseError
  • MalformedSignatureParams
  • UnsupportedAlgorithm(String)
  • ComponentError(component.ComponentError)
  • MissingRequiredComponent(component.ComponentIdentifier)
  • SignatureExpired
  • SignatureTooOld
  • InvalidSignature

The caller-supplied checks verify applies beyond the signature bytes themselves.

required_components is not optional: RFC 9421 §7.2 flags that a signature covering an insufficient or attacker-chosen set of components is a real attack surface, so callers must state what has to be covered (e.g. @method, @authority, date) rather than trusting whatever the signer claims to have covered.

now is caller-supplied rather than read from the system clock — this library has no built-in clock or replay protection by design, which keeps verification deterministic and identical across the Erlang and JavaScript targets, and trivially testable with fixed timestamps.

max_age_seconds, when given, additionally bounds now - created, independently of (and in addition to) the signature’s own expires.

pub type VerifyPolicy {
  VerifyPolicy(
    required_components: List(component.ComponentIdentifier),
    now: Int,
    max_age_seconds: option.Option(Int),
  )
}

Constructors

Values

pub fn parse(
  signature_input_header signature_input_header: String,
  label label: String,
) -> Result(params.SignatureParams, VerifyError)

Parses the Signature-Input header and extracts the parameters for label, so the caller can inspect keyid before picking a key to verify with.

pub fn verify(
  message message: message.Message,
  public_key public_key: eddsa.PublicKey,
  signature_params signature_params: params.SignatureParams,
  signature_header signature_header: String,
  label label: String,
  policy policy: VerifyPolicy,
) -> Result(Nil, VerifyError)

Verifies message against signature_header under label, using public_key, the previously-parsed signature_params, and policy.

Checks run cheapest-first: policy.required_components coverage, algorithm (UnsupportedAlgorithm for anything other than "ed25519" — the same algorithm-confusion guard as signer.sign), expiry, max age, and finally the signature bytes themselves.

For a message signed multiple times under different labels, call verify once per label — signature_header may hold several labeled signatures at once (RFC 9421’s dictionary model), and each is checked independently against its own signature_params and policy.

Search Document