identity_kit/sd_jwt_vc/error.rs
1//! Errors of SD-JWT parsing, processing and building.
2
3use super::ClaimPath;
4use crate::jose::JwsError;
5
6/// Why an SD-JWT could not be parsed, processed, selected from or built.
7#[derive(Debug, thiserror::Error)]
8#[non_exhaustive]
9pub enum SdJwtError {
10 /// The issuer-signed JWT or the key binding JWT is not a compact JWS this crate decodes.
11 #[error("invalid JWS: {0}")]
12 Jws(#[from] JwsError),
13 /// The compact serialization is malformed: no `~`, an empty disclosure.
14 #[error("invalid SD-JWT: {0}")]
15 Format(String),
16 /// A disclosure is not base64url of a JSON array of the right shape.
17 #[error("invalid disclosure {disclosure:?}: {reason}")]
18 InvalidDisclosure {
19 /// The encoded disclosure.
20 disclosure: String,
21 /// What is wrong with it.
22 reason: String,
23 },
24 /// The same disclosure is given twice.
25 #[error("disclosure {0:?} is given twice")]
26 DuplicateDisclosure(String),
27 /// The issuer-signed JWT payload is not a JSON object, or `_sd`, `...` or `_sd_alg` is
28 /// malformed.
29 #[error("invalid SD-JWT payload: {0}")]
30 Payload(String),
31 /// The `_sd_alg` names a hash algorithm this crate does not implement.
32 #[error("unsupported hash algorithm {0:?}")]
33 UnsupportedHashAlgorithm(String),
34 /// A digest appears more than once in the payload, directly or through disclosures.
35 #[error("digest {0:?} appears more than once")]
36 DuplicateDigest(String),
37 /// A disclosure matches no digest in the payload or in another disclosure.
38 #[error("disclosure {0:?} is referenced by no digest")]
39 UnusedDisclosure(String),
40 /// A disclosure of the wrong kind matches a digest: an array element disclosure in `_sd`,
41 /// or an object property disclosure in an array.
42 #[error("disclosure {disclosure:?} is not {expected}")]
43 WrongDisclosureKind {
44 /// The encoded disclosure.
45 disclosure: String,
46 /// `an object property disclosure` or `an array element disclosure`.
47 expected: &'static str,
48 },
49 /// A disclosure names the reserved claim `_sd` or `...`.
50 #[error("disclosure claim name {0:?} is reserved")]
51 ReservedClaimName(String),
52 /// A disclosure names a claim that already exists at the level of its `_sd`.
53 #[error("claim {name:?} at {path} is both disclosed and present")]
54 DuplicateClaim {
55 /// The claim name.
56 name: String,
57 /// The object it is duplicated in.
58 path: ClaimPath,
59 },
60 /// A disclosure was selected without the disclosure whose value references it.
61 #[error("disclosure {disclosure:?} needs the disclosure {parent:?} it is nested in")]
62 MissingParentDisclosure {
63 /// The encoded disclosure selected.
64 disclosure: String,
65 /// The encoded disclosure it needs.
66 parent: String,
67 },
68 /// A path to conceal or disclose selects no claim.
69 #[error("no claim at {0}")]
70 NoSuchClaim(ClaimPath),
71 /// A claim cannot be made selectively disclosable: it is `_sd` or `...`, or a profile
72 /// forbids it.
73 #[error("claim at {path} cannot be selectively disclosable: {reason}")]
74 NotConcealable {
75 /// The claim.
76 path: ClaimPath,
77 /// Why.
78 reason: String,
79 },
80 /// The claims to issue nest deeper than [`SdJwtBuilder::MAX_DEPTH`](super::SdJwtBuilder::MAX_DEPTH)
81 /// containers, which no parser of this crate would read back.
82 #[error("the claims nest deeper than {max} containers")]
83 TooDeep {
84 /// The deepest nesting the builder accepts.
85 max: usize,
86 },
87 /// The key binding JWT is present where an SD-JWT without key binding was expected, or
88 /// missing.
89 #[error("{0}")]
90 KeyBinding(String),
91}