identity_credential/presentation/
jwp_presentation_builder.rs

1// Copyright 2020-2024 IOTA Stiftung, Fondazione Links
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::error::Error;
5use crate::error::Result;
6use jsonprooftoken::jwp::header::PresentationProtectedHeader;
7use jsonprooftoken::jwp::issued::JwpIssued;
8use jsonprooftoken::jwp::presented::JwpPresentedBuilder;
9
10/// Used to construct a JwpPresentedBuilder and handle the selective disclosure of attributes.
11// - @context MUST NOT be blinded
12// - id MUST be blinded
13// - type MUST NOT be blinded
14// - issuer MUST NOT be blinded
15// - issuanceDate MUST be blinded (if Timeframe Revocation mechanism is used)
16// - expirationDate MUST be blinded (if Timeframe Revocation mechanism is used)
17// - credentialSubject (Users have to choose which attribute must be blinded)
18// - credentialSchema MUST NOT be blinded
19// - credentialStatus MUST NOT be blinded
20// - refreshService MUST NOT be blinded (probably will be used for Timeslot Revocation mechanism)
21// - termsOfUse NO reason to use it in ZK VC (will be in any case blinded)
22// - evidence (Users have to choose which attribute must be blinded)
23pub struct SelectiveDisclosurePresentation {
24  jwp_builder: JwpPresentedBuilder,
25}
26
27impl SelectiveDisclosurePresentation {
28  /// Initialize a presentation starting from an Issued JWP.
29  /// The following properties are concealed by default:
30  ///
31  ///   - `exp`
32  ///   - `expirationDate`
33  ///   - `issuanceDate`
34  ///   - `jti`
35  ///   - `nbf`
36  ///   - `sub`
37  ///   - `termsOfUse`
38  ///   - `vc.credentialStatus.revocationBitmapIndex`
39  ///   - `vc.credentialSubject.id`
40  pub fn new(issued_jwp: &JwpIssued) -> Self {
41    let mut jwp_builder = JwpPresentedBuilder::new(issued_jwp);
42
43    jwp_builder.set_undisclosed("jti").ok(); // contains the credential's id, provides linkability
44
45    jwp_builder.set_undisclosed("issuanceDate").ok(); // Depending on the revocation method used it will be necessary or not
46    jwp_builder.set_undisclosed("nbf").ok();
47
48    jwp_builder.set_undisclosed("expirationDate").ok(); // Depending on the revocation method used it will be necessary or not
49    jwp_builder.set_undisclosed("exp").ok();
50
51    jwp_builder.set_undisclosed("termsOfUse").ok(); // Provides linkability so, there is NO reason to use it in ZK VC
52
53    jwp_builder
54      .set_undisclosed("vc.credentialStatus.revocationBitmapIndex")
55      .ok();
56
57    jwp_builder.set_undisclosed("vc.credentialSubject.id").ok();
58    jwp_builder.set_undisclosed("sub").ok();
59
60    Self { jwp_builder }
61  }
62
63  /// Selectively conceal "credentialSubject" attributes.
64  /// # Example
65  /// ```ignore
66  /// {
67  ///     "id": 1234,
68  ///     "name": "Alice",
69  ///     "mainCourses": ["Object-oriented Programming", "Mathematics"],
70  ///     "degree": {
71  ///         "type": "BachelorDegree",
72  ///         "name": "Bachelor of Science and Arts",
73  ///     },
74  ///     "GPA": "4.0",
75  /// }
76  /// ```
77  /// If you want to undisclose for example the Mathematics course and the name of the degree:
78  /// ```ignore
79  /// presentation_builder.conceal_in_subject("mainCourses[1]");
80  /// presentation_builder.conceal_in_subject("degree.name");
81  /// ```
82  pub fn conceal_in_subject(&mut self, path: &str) -> Result<(), Error> {
83    let _ = self
84      .jwp_builder
85      .set_undisclosed(&("vc.credentialSubject.".to_owned() + path))
86      .map_err(|_| Error::SelectiveDisclosureError);
87    Ok(())
88  }
89
90  /// Undisclose "evidence" attributes.
91  /// # Example
92  /// ```ignore
93  /// {
94  ///   "id": "https://example.edu/evidence/f2aeec97-fc0d-42bf-8ca7-0548192d4231",
95  ///   "type": ["DocumentVerification"],
96  ///   "verifier": "https://example.edu/issuers/14",
97  ///   "evidenceDocument": "DriversLicense",
98  ///   "subjectPresence": "Physical",
99  ///   "documentPresence": "Physical",
100  ///   "licenseNumber": "123AB4567"
101  /// }
102  /// ```
103  /// To conceal the `licenseNumber` field:
104  /// ```ignore
105  /// presentation_builder.conceal_in_evidence("licenseNumber");
106  /// ```
107  pub fn conceal_in_evidence(&mut self, path: &str) -> Result<(), Error> {
108    let _ = self
109      .jwp_builder
110      .set_undisclosed(&("vc.evidence.".to_owned() + path))
111      .map_err(|_| Error::SelectiveDisclosureError);
112    Ok(())
113  }
114
115  /// Set Presentation Protected Header.
116  pub fn set_presentation_header(&mut self, ph: PresentationProtectedHeader) {
117    self.jwp_builder.set_presentation_protected_header(ph);
118  }
119
120  /// Get the builder.
121  pub fn builder(&self) -> &JwpPresentedBuilder {
122    &self.jwp_builder
123  }
124}