use core::fmt;
use std::error::Error;
use super::{JwsAlgorithm, KeyType};
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[non_exhaustive]
pub enum JwkError {
#[error("missing JWK member `{0}`")]
MissingMember(&'static str),
#[error("JWK member `{0}` is not valid base64url")]
InvalidBase64Url(&'static str),
#[error("expected {expected} key, found `kty` {kty:?} with `crv` {crv:?}")]
UnexpectedKeyType {
expected: &'static str,
kty: String,
crv: Option<String>,
},
#[error("unsupported key type: `kty` {kty:?} with `crv` {crv:?}")]
UnsupportedKeyType {
kty: String,
crv: Option<String>,
},
#[error("invalid {key} key: {reason}")]
InvalidKey {
key: &'static str,
reason: String,
},
#[error("invalid {key} key: expected {expected} bytes, found {actual}")]
InvalidKeyLength {
key: &'static str,
expected: usize,
actual: usize,
},
#[error("invalid Multikey: {0}")]
InvalidMultikey(String),
#[error("unsupported multicodec 0x{0:x}")]
UnsupportedMulticodec(u64),
#[error("key is not a {expected:?} key")]
KeyMismatch {
expected: KeyType,
},
#[error("support for {key} keys requires the `{feature}` feature")]
FeatureDisabled {
key: &'static str,
feature: &'static str,
},
#[error("cannot build a jsonwebtoken decoding key: {0}")]
DecodingKey(String),
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[non_exhaustive]
pub enum VerificationError {
#[error("algorithm {0} is not supported by this verifier")]
UnsupportedAlgorithm(JwsAlgorithm),
#[error("key `alg` {key_alg:?} does not match {alg}")]
AlgorithmMismatch {
alg: JwsAlgorithm,
key_alg: String,
},
#[error("key is not meant for signature verification: {0}")]
KeyUse(&'static str),
#[error(transparent)]
Key(#[from] JwkError),
#[error("signature is {actual} bytes, expected {expected}")]
InvalidSignatureLength {
expected: usize,
actual: usize,
},
#[error("ECDSA signature appears to be DER-encoded; JWS requires the raw `r || s` form")]
DerEncodedSignature,
#[error("signature verification failed")]
InvalidSignature,
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum JwsError {
#[error("compact JWS must have exactly three parts separated by `.`, found {parts}")]
InvalidFormat {
parts: usize,
},
#[error("JWS {part} is not valid base64url")]
InvalidBase64Url {
part: &'static str,
},
#[error("invalid JWS protected header: {0}")]
InvalidHeader(String),
#[error("unsupported JWS algorithm {0:?}")]
UnsupportedAlgorithm(String),
#[error("unsupported critical header parameters {0:?}")]
UnsupportedCritical(Vec<String>),
#[error("unencoded payloads (`b64: false`) are not supported")]
UnencodedPayload,
#[error("invalid JWS payload: {0}")]
InvalidPayload(String),
#[error("header `alg` {header} does not match the signer's {signer}")]
AlgorithmMismatch {
header: JwsAlgorithm,
signer: JwsAlgorithm,
},
#[error("signing failed: {0}")]
Signer(#[source] SignError),
}
#[derive(Debug)]
pub struct SignError(Box<dyn Error + Send + Sync + 'static>);
impl SignError {
pub fn new<E: Error + Send + Sync + 'static>(error: E) -> Self {
Self(Box::new(error))
}
pub fn msg<M: fmt::Display>(message: M) -> Self {
Self(message.to_string().into())
}
pub fn inner(&self) -> &(dyn Error + Send + Sync + 'static) {
self.0.as_ref()
}
}
impl fmt::Display for SignError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl Error for SignError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
self.0.source()
}
}
impl From<Box<dyn Error + Send + Sync + 'static>> for SignError {
fn from(error: Box<dyn Error + Send + Sync + 'static>) -> Self {
Self(error)
}
}