generated from iotaledger/template
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsd_jwt.rs
103 lines (89 loc) · 3.01 KB
/
sd_jwt.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Copyright 2020-2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
use std::error::Error;
use async_trait::async_trait;
use josekit::jws::alg::hmac::HmacJwsSigner;
use josekit::jws::JwsHeader;
use josekit::jws::HS256;
use josekit::jwt::JwtPayload;
use josekit::jwt::{self};
use sd_jwt_payload::JsonObject;
use sd_jwt_payload::JwsSigner;
use sd_jwt_payload::KeyBindingJwtBuilder;
use sd_jwt_payload::SdJwt;
use sd_jwt_payload::SdJwtBuilder;
use sd_jwt_payload::Sha256Hasher;
use serde_json::json;
struct HmacSignerAdapter(HmacJwsSigner);
#[async_trait]
impl JwsSigner for HmacSignerAdapter {
type Error = josekit::JoseError;
async fn sign(&self, header: &JsonObject, payload: &JsonObject) -> Result<Vec<u8>, Self::Error> {
let header = JwsHeader::from_map(header.clone())?;
let payload = JwtPayload::from_map(payload.clone())?;
let jws = jwt::encode_with_signer(&payload, &header, &self.0)?;
Ok(jws.into_bytes())
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let object = json!({
"sub": "user_42",
"given_name": "John",
"family_name": "Doe",
"email": "[email protected]",
"phone_number": "+1-202-555-0101",
"phone_number_verified": true,
"address": {
"street_address": "123 Main St",
"locality": "Anytown",
"region": "Anystate",
"country": "US"
},
"birthdate": "1940-01-01",
"updated_at": 1570000000,
"nationalities": [
"US",
"DE"
]
});
let key = b"0123456789ABCDEF0123456789ABCDEF";
let signer = HmacSignerAdapter(HS256.signer_from_bytes(key)?);
let sd_jwt = SdJwtBuilder::new(object)?
.make_concealable("/email")?
.make_concealable("/phone_number")?
.make_concealable("/address/street_address")?
.make_concealable("/address")?
.make_concealable("/nationalities/0")?
.add_decoys("/nationalities", 1)?
.add_decoys("", 2)?
.require_key_binding(sd_jwt_payload::RequiredKeyBinding::Kid("key1".to_string()))
.finish(&signer, "HS256")
.await?;
println!("raw object: {}", serde_json::to_string_pretty(sd_jwt.claims())?);
// Issuer sends the SD-JWT with all its disclosures to its holder.
let received_sd_jwt = sd_jwt.presentation();
let sd_jwt = received_sd_jwt.parse::<SdJwt>()?;
let hasher = Sha256Hasher::new();
let kb_jwt = KeyBindingJwtBuilder::new()
.aud("https://verifier.example.com")
.nonce("abcdefghi")
.iat(164389238943)
.finish(&sd_jwt, &hasher, "HS256", &signer)
.await?;
// The holder can withhold from a verifier any concealable claim by calling `conceal`.
let (presented_sd_jwt, _removed_disclosures) = sd_jwt
.into_presentation(&hasher)?
.conceal("/email")?
.conceal("/nationalities/0")?
.attach_key_binding_jwt(kb_jwt)
.finish()?;
// The holder send its token to a verifier.
let received_sd_jwt = presented_sd_jwt.presentation();
let sd_jwt = received_sd_jwt.parse::<SdJwt>()?;
println!(
"object to verify: {}",
serde_json::to_string_pretty(&sd_jwt.into_disclosed_object(&hasher)?)?
);
Ok(())
}