1use serde::{Deserialize, Serialize};
16
17use crate::{
18 jpa::algs::{PresentationProofAlgorithm, ProofAlgorithm},
19 jpt::claims::Claims, jwk::key::Jwk,
20};
21
22#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
23pub struct IssuerProtectedHeader {
25 #[serde(skip_serializing_if = "Option::is_none")]
27 typ: Option<String>,
28 alg: ProofAlgorithm,
30 #[serde(skip_serializing_if = "Option::is_none")]
32 kid: Option<String>,
33 #[serde(skip_serializing_if = "Option::is_none")]
36 cid: Option<String>,
37 #[serde(skip_serializing_if = "Option::is_none")]
39 claims: Option<Claims>,
40 #[serde(skip_serializing_if = "Option::is_none")]
44 crit: Option<Vec<String>>,
45 #[serde(skip_serializing_if = "Option::is_none")]
48 iss: Option<String>,
49 #[serde(skip_serializing_if = "Option::is_none")]
53 proof_key: Option<Jwk>,
54}
55
56impl IssuerProtectedHeader {
57 pub fn new(alg: ProofAlgorithm) -> Self {
59 Self {
60 typ: Some("JPT".to_owned()),
61 alg,
62 kid: None,
63 cid: None,
64 claims: None,
65 crit: None,
66 iss: None,
67 proof_key: None,
68 }
69 }
70
71 pub fn alg(&self) -> ProofAlgorithm {
73 self.alg
74 }
75
76 pub fn typ(&self) -> Option<&String> {
78 self.typ.as_ref()
79 }
80
81 pub fn set_typ(&mut self, value: Option<String>) {
83 self.typ = value;
84 }
85
86 pub fn kid(&self) -> Option<&String> {
88 self.kid.as_ref()
89 }
90
91 pub fn set_kid(&mut self, value: Option<String>) {
93 self.kid = value;
94 }
95
96 pub fn cid(&self) -> Option<&String> {
98 self.cid.as_ref()
99 }
100
101 pub fn set_cid(&mut self, value: Option<String>) {
103 self.cid = value;
104 }
105
106 pub fn claims(&self) -> Option<&Claims> {
108 self.claims.as_ref()
109 }
110
111 pub(crate) fn set_claims(&mut self, value: Option<Claims>) {
113 self.claims = value;
114 }
115
116 pub fn crit(&self) -> Option<&Vec<String>> {
118 self.crit.as_ref()
119 }
120
121 pub fn set_crit(&mut self, value: Option<Vec<String>>) {
123 self.crit = value;
124 }
125
126 pub fn iss(&self) -> Option<&String> {
128 self.iss.as_ref()
129 }
130
131 pub fn set_iss(&mut self, value: Option<String>) {
133 self.iss = value;
134 }
135
136 pub fn proof_key(&self) -> Option<Jwk> {
138 self.proof_key.clone()
139 }
140
141 pub fn set_proof_key(&mut self, value: Option<Jwk>) {
143 self.proof_key = value;
144 }
145
146}
147
148#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
149pub struct PresentationProtectedHeader {
150 alg: PresentationProofAlgorithm,
151 #[serde(skip_serializing_if = "Option::is_none")]
153 kid: Option<String>,
154 #[serde(skip_serializing_if = "Option::is_none")]
157 aud: Option<String>,
158 #[serde(skip_serializing_if = "Option::is_none")]
160 nonce: Option<String>,
161 #[serde(skip_serializing_if = "Option::is_none")]
163 typ: Option<String>,
164 #[serde(skip_serializing_if = "Option::is_none")]
168 crit: Option<Vec<String>>,
169 #[serde(skip_serializing_if = "Option::is_none")]
172 iss: Option<String>,
173 #[serde(skip_serializing_if = "Option::is_none")]
177 presentation_key: Option<Jwk>,
178}
179
180impl PresentationProtectedHeader {
181 pub fn new(alg: PresentationProofAlgorithm) -> Self {
183 Self {
184 alg,
185 kid: None,
186 aud: None,
187 nonce: None,
188 typ: None,
189 crit: None,
190 iss: None,
191 presentation_key: None,
192 }
193 }
194
195 pub fn alg(&self) -> PresentationProofAlgorithm {
197 self.alg
198 }
199
200 pub fn kid(&self) -> Option<&String> {
202 self.kid.as_ref()
203 }
204
205 pub fn set_kid(&mut self, value: Option<String>) {
207 self.kid = value;
208 }
209
210 pub fn aud(&self) -> Option<&String> {
212 self.aud.as_ref()
213 }
214
215 pub fn set_aud(&mut self, value: Option<String>) {
217 self.aud = value;
218 }
219
220 pub fn nonce(&self) -> Option<&String> {
222 self.nonce.as_ref()
223 }
224
225 pub fn set_nonce(&mut self, value: Option<String>) {
227 self.nonce = value;
228 }
229
230 pub fn typ(&self) -> Option<&String> {
232 self.typ.as_ref()
233 }
234
235 pub fn set_typ(&mut self, value: Option<String>) {
237 self.typ = value;
238 }
239
240 pub fn crit(&self) -> Option<&Vec<String>> {
242 self.crit.as_ref()
243 }
244
245 pub fn set_crit(&mut self, value: Option<Vec<String>>) {
247 self.crit = value;
248 }
249
250 pub fn iss(&self) -> Option<&String> {
252 self.iss.as_ref()
253 }
254
255 pub fn set_iss(&mut self, value: Option<String>) {
257 self.iss = value;
258 }
259
260 pub fn presentation_key(&self) -> Option<Jwk> {
262 self.presentation_key.clone()
263 }
264
265 pub fn set_presentation_key(&mut self, value: Option<Jwk>) {
267 self.presentation_key = value;
268 }
269
270}
271
272#[cfg(test)]
273mod tests {
274 use serde_json::json;
275
276 use super::*;
277
278 #[test]
279 fn test_default_issuer_protected_header() {
280 let header = IssuerProtectedHeader::new(ProofAlgorithm::BBS);
281 assert_eq!(header.alg(), ProofAlgorithm::BBS);
282 assert_eq!(header.typ(), Some(&"JPT".to_owned()));
283 assert_eq!(header.kid(), None);
284 assert_eq!(header.cid(), None);
285 assert_eq!(header.claims(), None);
286 assert_eq!(header.crit(), None);
287 assert_eq!(header.iss(), None);
288 assert_eq!(header.proof_key(), None);
289 }
290
291 #[test]
292 fn test_custom_issuer_protected_header(){
293 let json = json!({
294 "kid": "HjfcpyjuZQ-O8Ye2hQnNbT9RbbnrobptdnExR0DUjU8",
295 "alg": "BBS",
296 "typ": "JPT",
297 "iss": "example.com",
298 "cid": "example.com/cid/123",
299 "claims": [
300 "iat",
301 "exp",
302 "family_name",
303 "given_name",
304 "email",
305 "address",
306 "age_over_21"
307 ],
308 "crit": [
309 "critical_extension_1",
310 "critical_extension_2",
311 ],
312 "proof_key" : {
313 "kty": "EC",
314 "crv": "BLS12381G2",
315 "x": "AizYfy-snuLWBAQjzm5UJcmXkNe4DPVbcqFha7i7hgmpiDgGHVUdqqM8YWmWkzi-DBSTXPozzlvnB1TZXcgXtYPla9M1iyK3evsD3Eoyo3ClR1_I_Pfmlk_signHOz9i",
316 "y": "A8PoKJou9-4t93kYDlIX_BGMgAqjIaZIW5TRQwusD4lDhcmSZy9hY5Sl2NxERhA8ERq2NLklV6dethvprgZ3hKfzrjU97MtkcY2ql-390o08o_C475nIAXqtgDqZwg-X",
317 "d": "UFjZc6H5vhHAmPcchdlRLnfNKmSCbnqDylT3aKZYSW4"
318 }
319 });
320 let claims: Claims = serde_json::from_value(json!(["iat", "exp", "family_name", "given_name", "email", "address", "age_over_21"]))
321 .expect("Failed to deserialize Claims");
322 let jwk: Jwk = serde_json::from_value(json!({
323 "kty": "EC",
324 "crv": "BLS12381G2",
325 "x": "AizYfy-snuLWBAQjzm5UJcmXkNe4DPVbcqFha7i7hgmpiDgGHVUdqqM8YWmWkzi-DBSTXPozzlvnB1TZXcgXtYPla9M1iyK3evsD3Eoyo3ClR1_I_Pfmlk_signHOz9i",
326 "y": "A8PoKJou9-4t93kYDlIX_BGMgAqjIaZIW5TRQwusD4lDhcmSZy9hY5Sl2NxERhA8ERq2NLklV6dethvprgZ3hKfzrjU97MtkcY2ql-390o08o_C475nIAXqtgDqZwg-X",
327 "d": "UFjZc6H5vhHAmPcchdlRLnfNKmSCbnqDylT3aKZYSW4"
328 })).expect("Failed to deserialize Jwk");
329 let header: IssuerProtectedHeader = serde_json::from_value(json).expect("Failed to deserialize IssuerProtectedHeader");
330 assert_eq!(header.alg(), ProofAlgorithm::BBS);
331 assert_eq!(header.typ(), Some(&"JPT".to_owned()));
332 assert_eq!(header.kid(), Some(&"HjfcpyjuZQ-O8Ye2hQnNbT9RbbnrobptdnExR0DUjU8".to_owned()));
333 assert_eq!(header.cid(), Some(&"example.com/cid/123".to_owned()));
334 assert_eq!(header.claims(), Some(&claims));
335 assert_eq!(header.crit(), Some(&vec!["critical_extension_1".to_owned(), "critical_extension_2".to_owned()]));
336 assert_eq!(header.proof_key(), Some(jwk));
337 assert_eq!(header.iss(), Some(&"example.com".to_owned()));
338
339 }
340
341 #[test]
342 fn test_default_presentation_protected_header() {
343 let header = PresentationProtectedHeader::new(PresentationProofAlgorithm::BBS_SHAKE256);
344 assert_eq!(header.alg(), PresentationProofAlgorithm::BBS_SHAKE256);
345 assert_eq!(header.kid(), None);
346 assert_eq!(header.aud(), None);
347 assert_eq!(header.nonce(), None);
348 assert_eq!(header.typ(), None);
349 assert_eq!(header.crit(), None);
350 assert_eq!(header.iss(), None);
351 assert_eq!(header.presentation_key(), None);
352 }
353
354 #[test]
355 fn test_custom_presentation_protected_header(){
356 let json = json!({
357 "kid": "HjfcpyjuZQ-O8Ye2hQnNbT9RbbnrobptdnExR0DUjU8",
358 "alg": "BBS",
359 "typ": "JPT",
360 "iss": "example.com",
361 "aud": "audience_example",
362 "crit": [
363 "critical_extension_1",
364 "critical_extension_2",
365 ],
366 "presentation_key" : {
367 "kty": "EC",
368 "crv": "BLS12381G2",
369 "x": "AizYfy-snuLWBAQjzm5UJcmXkNe4DPVbcqFha7i7hgmpiDgGHVUdqqM8YWmWkzi-DBSTXPozzlvnB1TZXcgXtYPla9M1iyK3evsD3Eoyo3ClR1_I_Pfmlk_signHOz9i",
370 "y": "A8PoKJou9-4t93kYDlIX_BGMgAqjIaZIW5TRQwusD4lDhcmSZy9hY5Sl2NxERhA8ERq2NLklV6dethvprgZ3hKfzrjU97MtkcY2ql-390o08o_C475nIAXqtgDqZwg-X",
371 "d": "UFjZc6H5vhHAmPcchdlRLnfNKmSCbnqDylT3aKZYSW4"
372 },
373 "nonce": "wrmBRkKtXjQ"
374 });
375
376 let jwk: Jwk = serde_json::from_value(json!({
377 "kty": "EC",
378 "crv": "BLS12381G2",
379 "x": "AizYfy-snuLWBAQjzm5UJcmXkNe4DPVbcqFha7i7hgmpiDgGHVUdqqM8YWmWkzi-DBSTXPozzlvnB1TZXcgXtYPla9M1iyK3evsD3Eoyo3ClR1_I_Pfmlk_signHOz9i",
380 "y": "A8PoKJou9-4t93kYDlIX_BGMgAqjIaZIW5TRQwusD4lDhcmSZy9hY5Sl2NxERhA8ERq2NLklV6dethvprgZ3hKfzrjU97MtkcY2ql-390o08o_C475nIAXqtgDqZwg-X",
381 "d": "UFjZc6H5vhHAmPcchdlRLnfNKmSCbnqDylT3aKZYSW4"
382 })).expect("Failed to deserialize Jwk");
383 let header: PresentationProtectedHeader = serde_json::from_value(json).expect("Failed to deserialize IssuerProtectedHeader");
384 assert_eq!(header.alg(), PresentationProofAlgorithm::BBS);
385 assert_eq!(header.typ(), Some(&"JPT".to_owned()));
386 assert_eq!(header.kid(), Some(&"HjfcpyjuZQ-O8Ye2hQnNbT9RbbnrobptdnExR0DUjU8".to_owned()));
387 assert_eq!(header.crit(), Some(&vec!["critical_extension_1".to_owned(), "critical_extension_2".to_owned()]));
388 assert_eq!(header.presentation_key(), Some(jwk));
389 assert_eq!(header.iss(), Some(&"example.com".to_owned()));
390 assert_eq!(header.aud(), Some(&"audience_example".to_owned()));
391 assert_eq!(header.nonce(), Some(&"wrmBRkKtXjQ".to_owned()));
392
393 }
394
395 #[test]
396 fn test_set_issuer_protected_header() {
397 let mut header = IssuerProtectedHeader::new(ProofAlgorithm::BBS);
398 let claims: Claims = serde_json::from_value(json!(["iat", "exp", "family_name", "given_name", "email", "address", "age_over_21"]))
399 .expect("Failed to deserialize Claims");
400 header.set_kid(Some("HjfcpyjuZQ-O8Ye2hQnNbT9RbbnrobptdnExR0DUjU8".to_owned()));
401 header.set_cid(Some("example.com/cid/123".to_owned()));
402 header.set_claims(Some(claims));
403 header.set_crit(Some(vec!["critical_extension_1".to_owned(), "critical_extension_2".to_owned()]));
404 header.set_iss(Some("example.com".to_owned()));
405
406 let json = json!({
407 "kid": "HjfcpyjuZQ-O8Ye2hQnNbT9RbbnrobptdnExR0DUjU8",
408 "alg": "BBS",
409 "typ": "JPT",
410 "iss": "example.com",
411 "cid": "example.com/cid/123",
412 "claims": [
413 "iat",
414 "exp",
415 "family_name",
416 "given_name",
417 "email",
418 "address",
419 "age_over_21"
420 ],
421 "crit": [
422 "critical_extension_1",
423 "critical_extension_2",
424 ],
425 });
426
427 let header_json: IssuerProtectedHeader = serde_json::from_value(json).expect("Failed to deserialize IssuerProtectedHeader");
428 assert_eq!(header, header_json);
429
430 }
431 #[test]
432 fn test_set_presentation_protected_header() {
433 let mut header = PresentationProtectedHeader::new(PresentationProofAlgorithm::BBS_SHAKE256);
434
435 header.set_kid(Some("HjfcpyjuZQ-O8Ye2hQnNbT9RbbnrobptdnExR0DUjU8".to_owned()));
436 header.set_crit(Some(vec!["critical_extension_1".to_owned(), "critical_extension_2".to_owned()]));
437 header.set_iss(Some("example.com".to_owned()));
438 header.set_aud(Some("audience_example".to_owned()));
439 header.set_nonce(Some("wrmBRkKtXjQ".to_owned()));
440 header.set_typ(Some("JPT".to_owned()));
441 let json = json!({
442 "kid": "HjfcpyjuZQ-O8Ye2hQnNbT9RbbnrobptdnExR0DUjU8",
443 "alg": "BBS-SHAKE256",
444 "typ": "JPT",
445 "iss": "example.com",
446 "aud": "audience_example",
447 "crit": [
448 "critical_extension_1",
449 "critical_extension_2",
450 ],
451 "nonce": "wrmBRkKtXjQ"
452 });
453
454 let header_json: PresentationProtectedHeader = serde_json::from_value(json).expect("Failed to deserialize PresentationProtectedHeader");
455 assert_eq!(header, header_json);
456
457 }
458
459}