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}