1use bh_jws_utils::{jwt, JwkPublic, JwtVerifier as _, SignatureVerifier, SigningAlgorithm};
17use bherror::{
18 traits::{ForeignBoxed, ForeignError, PropagateError},
19 Error,
20};
21pub use iref::Uri;
22pub use jwt::claims::SecondsSinceEpoch;
23use serde::{Deserialize, Serialize};
24pub use serde_json::{Map, Value};
25use yoke::Yoke;
26
27use crate::error::{FormatError, Result, SignatureError};
28mod disclosure;
29mod error;
30mod path;
31pub(crate) mod path_map;
32
33pub use disclosure::*;
34pub(crate) use error::*;
35pub use path::*;
36
37use crate::{
38 utils::SD_ALG_FIELD_NAME, Hasher, HashingAlgorithm, IssuerJwt, IssuerJwtHeader,
39 IssuerPublicKeyLookup,
40};
41
42#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
49pub struct CnfClaim {
50 pub jwk: JwkPublic,
52}
53
54pub type JsonObject = Map<String, Value>;
56
57#[inline(always)]
59pub(crate) fn into_object(value: Value) -> JsonObject {
60 if let Value::Object(object) = value {
61 object
62 } else {
63 panic!("Argument wasn't an object")
64 }
65}
66
67#[macro_export]
74macro_rules! json_object {
75 ($stuff:tt) => {
76 match ::serde_json::json!($stuff) {
77 ::serde_json::Value::Object(o) => o,
78 _ => unreachable!("JSON literal wasn't an object"),
79 }
80 };
81}
82
83pub(crate) const SD: &str = "_sd";
84pub(crate) const ELLIPSIS: &str = "...";
85pub(crate) static RESERVED_CLAIM_NAMES: &[&str] = &[SD, SD_ALG_FIELD_NAME, ELLIPSIS];
86
87pub(crate) struct ParsedSdJwtIssuance<State> {
89 pub(crate) jwt: jwt::Token<IssuerJwtHeader, IssuerJwt, State>,
90 pub(crate) disclosures: Vec<Disclosure>,
91}
92
93#[cfg_attr(test, derive(Debug))]
95pub struct IssuedSdJwt(pub(crate) ParsedSdJwtIssuance<jwt::token::Signed>);
96
97impl IssuedSdJwt {
98 pub fn into_string_compact(self) -> String {
100 crate::SdJwt::new(
101 self.0.jwt.into(),
102 self.0
103 .disclosures
104 .into_iter()
105 .map(Disclosure::into_string)
106 .collect(),
107 )
108 .to_string()
109 }
110}
111
112#[cfg_attr(test, derive(Debug))]
114pub(crate) struct SdJwtUnverified<'a>(pub(crate) ParsedSdJwtIssuance<jwt::Unverified<'a>>);
115
116impl SdJwtUnverified<'_> {
117 pub(crate) async fn verify<'a>(
118 self,
119 issuer_public_key_lookup: &impl IssuerPublicKeyLookup,
120 get_signature_verifier: impl FnOnce(SigningAlgorithm) -> Option<&'a dyn SignatureVerifier>,
121 ) -> Result<(SdJwtSignatureVerified, SigningAlgorithm, JwkPublic), SignatureError> {
122 let (verifier, alg, key) = self
124 .get_signature_verifier_and_public_key(issuer_public_key_lookup, get_signature_verifier)
125 .await?;
126 let unverified_jwt = self.0.jwt;
129 let jwt = verifier
130 .verify_jwt_signature(unverified_jwt, &key)
131 .foreign_boxed_err(|| SignatureError::InvalidJwtSignature)?;
132
133 let disclosures = self.0.disclosures;
134
135 Ok((
136 SdJwtSignatureVerified(ParsedSdJwtIssuance { jwt, disclosures }),
137 alg,
138 key,
139 ))
140 }
141
142 async fn get_signature_verifier_and_public_key<'a>(
165 &self,
166 issuer_public_key_lookup: &impl IssuerPublicKeyLookup,
167 get_signature_verifier: impl FnOnce(SigningAlgorithm) -> Option<&'a dyn SignatureVerifier>,
168 ) -> Result<(&'a dyn SignatureVerifier, SigningAlgorithm, JwkPublic), SignatureError> {
169 let key = issuer_public_key_lookup
170 .lookup(&self.0.jwt.claims().iss, self.0.jwt.header())
171 .await
172 .with_err(|| SignatureError::PublicKeyLookupFailed)?;
173
174 let alleged_signing_algorithm = self.0.jwt.header().alg;
175 let verifier = get_signature_verifier(alleged_signing_algorithm).ok_or_else(|| {
176 Error::root(SignatureError::MissingSignatureVerifier(
177 alleged_signing_algorithm,
178 ))
179 })?;
180
181 Ok((verifier, alleged_signing_algorithm, key))
182 }
183}
184
185impl crate::SdJwt {
186 pub(crate) fn parse(&self) -> Result<SdJwtUnverified<'_>, FormatError> {
188 let jwt =
201 jwt::Token::parse_unverified(&self.jwt).foreign_err(|| FormatError::NonParseableJwt)?;
202
203 let disclosures = self
204 .disclosures
205 .iter()
206 .cloned()
207 .map(Disclosure::try_from)
208 .collect::<Result<Vec<_>, _>>()?;
209
210 Ok(SdJwtUnverified(ParsedSdJwtIssuance { jwt, disclosures }))
211 }
212
213 pub(crate) async fn to_signature_verified_sd_jwt<'a>(
214 &self,
215 issuer_public_key_lookup: &impl IssuerPublicKeyLookup,
216 get_signature_verifier: impl FnOnce(SigningAlgorithm) -> Option<&'a dyn SignatureVerifier>,
217 ) -> Result<(SdJwtSignatureVerified, SigningAlgorithm, JwkPublic), crate::Error> {
218 self.parse()
219 .match_err(|format_error| crate::Error::Format(format_error.clone()))?
220 .verify(issuer_public_key_lookup, get_signature_verifier)
221 .await
222 .match_err(|signature_error| crate::Error::Signature(signature_error.clone()))
223 }
224}
225
226pub(crate) struct SdJwtSignatureVerified(ParsedSdJwtIssuance<jwt::Verified>);
230
231impl SdJwtSignatureVerified {
232 pub(crate) fn into_decoded(
236 self,
237 get_hasher: impl Fn(HashingAlgorithm) -> Option<Box<dyn Hasher>>,
238 ) -> Result<SdJwtDecoded, crate::Error> {
239 SdJwtDecoded::new(self, get_hasher)
240 }
241}
242
243pub(crate) struct SdJwtDecoded {
247 decoded_claims: IssuerJwt,
248 disclosures_by_path: Yoke<DisclosureByPathTable<'static>, Vec<Disclosure>>,
249 hasher: Box<dyn Hasher>,
250}
251
252impl SdJwtDecoded {
253 pub(crate) fn new(
254 verified_sd_jwt: SdJwtSignatureVerified,
255 get_hasher: impl Fn(HashingAlgorithm) -> Option<Box<dyn Hasher>>,
256 ) -> Result<Self, crate::Error> {
257 let ParsedSdJwtIssuance { jwt, disclosures } = verified_sd_jwt.0;
258 let full_payload = jwt.claims().to_object();
262
263 let mut owned_output = None;
264
265 let disclosures_by_path = Yoke::try_attach_to_cart(disclosures, |disclosures| {
267 let (decoded_claims, hasher, disclosures_by_path) =
268 crate::decoder::decode_disclosed_claims(&full_payload, disclosures, get_hasher)
269 .match_err(|err| crate::Error::Decoding(err.clone()))?;
270
271 owned_output = Some((decoded_claims, hasher));
272
273 Ok(disclosures_by_path)
274 })?;
275
276 let (decoded_claims, hasher) = owned_output.unwrap();
277
278 let decoded_claims = serde_json::from_value(decoded_claims.into())
279 .foreign_err(|| crate::Error::Format(FormatError::InvalidVcSchema))?;
280
281 Ok(Self {
282 decoded_claims,
283 disclosures_by_path,
284 hasher,
285 })
286 }
287
288 pub(crate) fn disclosures_by_path(&self) -> &DisclosureByPathTable<'_> {
290 self.disclosures_by_path.get()
291 }
292
293 pub(crate) fn claims(&self) -> &IssuerJwt {
294 &self.decoded_claims
295 }
296
297 pub(crate) fn into_claims(self) -> IssuerJwt {
298 self.decoded_claims
299 }
300
301 pub(crate) fn key_binding_public_key(&self) -> &JwkPublic {
302 &self.decoded_claims.cnf.jwk
303 }
304
305 pub(crate) fn hasher(&self) -> &dyn Hasher {
306 &*self.hasher
307 }
308}
309
310