actpub_httpsig/error.rs
1//! Error types for [`actpub-httpsig`](crate).
2
3use thiserror::Error;
4
5/// Enumeration of every failure mode that this crate can surface.
6///
7/// The enum is non-exhaustive so that additional signature schemes or
8/// cryptographic algorithms can be added in minor releases without
9/// breaking downstream code.
10#[derive(Debug, Error)]
11#[non_exhaustive]
12pub enum Error {
13 /// The provided PEM document could not be parsed.
14 #[error("invalid PEM document: {0}")]
15 InvalidPem(String),
16
17 /// The PEM document had an unexpected `-----BEGIN <LABEL>-----` line.
18 #[error("unexpected PEM label `{0}`, expected one of: {1}")]
19 UnexpectedPemLabel(String, &'static str),
20
21 /// A PKCS#8 DER blob could not be decoded.
22 #[error("invalid PKCS#8 DER: {0}")]
23 InvalidPkcs8(String),
24
25 /// The key's algorithm identifier was not supported.
26 #[error("unsupported key algorithm: {0}")]
27 UnsupportedAlgorithm(String),
28
29 /// The RSA key size was outside the supported range.
30 #[error(
31 "unsupported RSA key size {0} bits; only {min}-{max} supported",
32 min = 2048,
33 max = 4096
34 )]
35 UnsupportedRsaSize(u32),
36
37 /// An underlying `aws-lc-rs` primitive failed.
38 #[error("cryptographic operation failed: {0}")]
39 Crypto(&'static str),
40
41 /// Generation of a new key failed at the RNG layer.
42 #[error("key generation failed: {0}")]
43 KeyGeneration(&'static str),
44
45 /// A signature's Base64 encoding was malformed.
46 #[error("invalid Base64 in signature: {0}")]
47 InvalidBase64(#[from] base64ct::Error),
48
49 /// Multibase decoding of a FEP-521a `publicKeyMultibase` failed.
50 #[error("invalid multibase: {0}")]
51 InvalidMultibase(#[from] multibase::Error),
52
53 /// The multicodec prefix on a Multikey was unrecognised or truncated.
54 #[error("invalid multikey codec prefix")]
55 InvalidMultikeyPrefix,
56
57 /// The raw key material following the multicodec prefix had the wrong length.
58 #[error("invalid multikey body length: expected {expected}, got {actual}")]
59 InvalidMultikeyLength {
60 /// Expected number of key bytes.
61 expected: usize,
62 /// Actual number of key bytes.
63 actual: usize,
64 },
65
66 /// A required HTTP header is missing.
67 #[error("missing HTTP header `{0}`")]
68 MissingHeader(&'static str),
69
70 /// An HTTP header's value was not valid UTF-8 or otherwise unparseable.
71 #[error("invalid HTTP header `{name}`: {reason}")]
72 InvalidHeader {
73 /// Header name that could not be parsed.
74 name: &'static str,
75 /// Human-readable reason.
76 reason: String,
77 },
78
79 /// The `Signature` header's parameter list was malformed.
80 #[error("malformed Signature header: {0}")]
81 MalformedSignatureHeader(String),
82
83 /// The signature did not verify against the provided key.
84 #[error("signature verification failed")]
85 VerificationFailed,
86
87 /// The resolver closure returned an error while fetching the signer's key.
88 #[error("key resolution failed: {0}")]
89 KeyResolution(String),
90
91 /// The `Digest` / `Content-Digest` header did not match the body.
92 #[error("digest mismatch: body SHA-256 did not match `Digest` header")]
93 DigestMismatch,
94
95 /// The requested digest algorithm is not supported.
96 #[error("unsupported digest algorithm `{0}`")]
97 UnsupportedDigestAlgorithm(String),
98
99 /// The signature-base string includes a header that the request does not carry.
100 #[error("cannot build signature base: required header `{0}` is absent from the request")]
101 RequiredHeaderAbsent(String),
102
103 /// A signature parameter required by the standard is missing.
104 #[error("required signature parameter `{0}` is missing")]
105 MissingSignatureParameter(&'static str),
106
107 /// The signature carried no `created` parameter and no `Date`
108 /// header, and the active [`VerifyPolicy`](crate::VerifyPolicy)
109 /// requires one.
110 #[error("no `created` parameter or `Date` header on a signature that requires freshness")]
111 TimestampMissing,
112
113 /// The signature is older than the policy's `max_age`.
114 #[error("signature is too old: timestamp {timestamp}, now {now}")]
115 TimestampTooOld {
116 /// The signed timestamp, either from `created` or the `Date` header.
117 timestamp: chrono::DateTime<chrono::Utc>,
118 /// The verifier's current wall-clock time.
119 now: chrono::DateTime<chrono::Utc>,
120 },
121
122 /// The signature claims to have been produced further in the future
123 /// than the policy's `max_clock_skew_future` tolerance allows.
124 #[error("signature claims a future timestamp: timestamp {timestamp}, now {now}")]
125 TimestampInFuture {
126 /// The signed timestamp.
127 timestamp: chrono::DateTime<chrono::Utc>,
128 /// The verifier's current wall-clock time.
129 now: chrono::DateTime<chrono::Utc>,
130 },
131
132 /// The signature's `expires` parameter indicates it has lapsed.
133 #[error("signature expired at {expires}, now {now}")]
134 TimestampExpired {
135 /// The `expires` parameter interpreted as a UTC timestamp.
136 expires: chrono::DateTime<chrono::Utc>,
137 /// The verifier's current wall-clock time.
138 now: chrono::DateTime<chrono::Utc>,
139 },
140}