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
-
VerifyPolicy( required_components: List(component.ComponentIdentifier), now: Int, max_age_seconds: option.Option(Int), )
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.