identity_credential/sd_jwt_vc/
presentation.rs

1// Copyright 2020-2024 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use super::Error;
5use super::Result;
6use super::SdJwtVc;
7use super::SdJwtVcClaims;
8
9use sd_jwt_payload_rework::Disclosure;
10use sd_jwt_payload_rework::Hasher;
11use sd_jwt_payload_rework::KeyBindingJwt;
12use sd_jwt_payload_rework::SdJwtPresentationBuilder;
13
14/// Builder structure to create an SD-JWT VC presentation.
15/// It allows users to conceal claims and attach a key binding JWT.
16#[derive(Debug, Clone)]
17pub struct SdJwtVcPresentationBuilder {
18  vc_claims: SdJwtVcClaims,
19  builder: SdJwtPresentationBuilder,
20}
21
22impl SdJwtVcPresentationBuilder {
23  /// Prepare a presentation for a given [`SdJwtVc`].
24  pub fn new(token: SdJwtVc, hasher: &dyn Hasher) -> Result<Self> {
25    let SdJwtVc {
26      mut sd_jwt,
27      parsed_claims: mut vc_claims,
28    } = token;
29    // Make sure to set the parsed claims back into the SD-JWT Token.
30    // The reason we do this is to make sure that the underlying SdJwtPresetationBuilder
31    // that operates on the wrapped SdJwt token can handle the claims.
32    std::mem::swap(sd_jwt.claims_mut(), &mut vc_claims.sd_jwt_claims);
33    let builder = sd_jwt.into_presentation(hasher).map_err(Error::SdJwt)?;
34
35    Ok(Self { vc_claims, builder })
36  }
37  /// Removes the disclosure for the property at `path`, conceiling it.
38  ///
39  /// ## Notes
40  /// - When concealing a claim more than one disclosure may be removed: the disclosure for the claim itself and the
41  ///   disclosures for any concealable sub-claim.
42  pub fn conceal(mut self, path: &str) -> Result<Self> {
43    self.builder = self.builder.conceal(path).map_err(Error::SdJwt)?;
44    Ok(self)
45  }
46
47  /// Removes all disclosures from this SD-JWT, resulting in a token that,
48  /// when presented, will have *all* selectively-disclosable properties
49  /// omitted.
50  pub fn conceal_all(mut self) -> Self {
51    self.builder = self.builder.conceal_all();
52    self
53  }
54
55  /// Discloses a value that was previously concealed.
56  /// # Notes
57  /// - This method may disclose multiple values, if the given path references a disclosable value stored within another
58  ///   disclosable value. That is, [disclose](Self::disclose) will unconceal the selectively disclosable value at
59  ///   `path` together with *all* its parents that are disclosable values themselves.
60  /// - By default *all* disclosable claims are disclosed, therefore this method can only be used to *undo* any
61  ///   concealment operations previously performed by either [Self::conceal] or [Self::conceal_all].
62  pub fn disclose(mut self, path: &str) -> Result<Self> {
63    self.builder = self.builder.disclose(path).map_err(Error::SdJwt)?;
64    Ok(self)
65  }
66
67  /// Adds a [`KeyBindingJwt`] to this [`SdJwtVc`]'s presentation.
68  pub fn attach_key_binding_jwt(mut self, kb_jwt: KeyBindingJwt) -> Self {
69    self.builder = self.builder.attach_key_binding_jwt(kb_jwt);
70    self
71  }
72
73  /// Returns the resulting [`SdJwtVc`] together with all removed disclosures.
74  pub fn finish(mut self) -> Result<(SdJwtVc, Vec<Disclosure>)> {
75    let (mut sd_jwt, disclosures) = self.builder.finish()?;
76    // Move the token's claim back into parsed VC claims.
77    std::mem::swap(sd_jwt.claims_mut(), &mut self.vc_claims.sd_jwt_claims);
78
79    Ok((SdJwtVc::new(sd_jwt, self.vc_claims), disclosures))
80  }
81}