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}