Skip to main content

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}