trustchain_http/
attestation_encryption_utils.rs1use std::collections::HashMap;
2
3use josekit::jwe::ECDH_ES;
4use josekit::jwk::Jwk;
5use josekit::jws::{JwsHeader, ES256K};
6use josekit::jwt::{self, JwtPayload};
7use serde_json::Value;
8use ssi::did::{Document, VerificationMethod};
9use ssi::jwk::JWK;
10
11use crate::attestation_utils::TrustchainCRError;
12
13pub struct Entity {}
14
15impl SignEncrypt for Entity {}
16
17impl DecryptVerify for Entity {}
18
19pub trait SignEncrypt {
21 fn sign(&self, payload: &JwtPayload, secret_key: &Jwk) -> Result<String, TrustchainCRError> {
23 let mut header = JwsHeader::new();
24 header.set_token_type("JWT");
25 let signer = ES256K.signer_from_jwk(secret_key)?;
26 let signed_jwt = jwt::encode_with_signer(payload, &header, &signer)?;
27 Ok(signed_jwt)
28 }
29 fn encrypt(&self, payload: &JwtPayload, public_key: &Jwk) -> Result<String, TrustchainCRError> {
33 let mut header = josekit::jwe::JweHeader::new();
34 header.set_token_type("JWT");
35 header.set_content_encryption("A128CBC-HS256");
36 header.set_content_encryption("A256GCM");
37
38 let encrypter = ECDH_ES.encrypter_from_jwk(public_key)?;
39 let encrypted_jwt = jwt::encode_with_encrypter(payload, &header, &encrypter)?;
40 Ok(encrypted_jwt)
41 }
42 fn sign_and_encrypt_claim(
44 &self,
45 payload: &JwtPayload,
46 secret_key: &Jwk,
47 public_key: &Jwk,
48 ) -> Result<String, TrustchainCRError> {
49 let signed_payload = self.sign(payload, secret_key)?;
50 let mut claims = JwtPayload::new();
51 claims.set_claim("claim", Some(Value::from(signed_payload)))?;
52 self.encrypt(&claims, public_key)
53 }
54}
55pub trait DecryptVerify {
57 fn decrypt(&self, value: &Value, secret_key: &Jwk) -> Result<JwtPayload, TrustchainCRError> {
59 let decrypter = ECDH_ES.decrypter_from_jwk(secret_key)?;
60 let (payload, _) = jwt::decode_with_decrypter(
61 value
62 .as_str()
63 .ok_or(TrustchainCRError::FailedToConvertToStr(value.clone()))?,
64 &decrypter,
65 )?;
66 Ok(payload)
67 }
68 fn decrypt_and_verify(
70 &self,
71 input: String,
72 secret_key: &Jwk,
73 public_key: &Jwk,
74 ) -> Result<JwtPayload, TrustchainCRError> {
75 let decrypter = ECDH_ES.decrypter_from_jwk(secret_key)?;
76 let (payload, _) = jwt::decode_with_decrypter(input, &decrypter)?;
77
78 let verifier = ES256K.verifier_from_jwk(public_key)?;
79 let claim = payload
80 .claim("claim")
81 .ok_or(TrustchainCRError::ClaimNotFound)?;
82 let (payload, _) = jwt::decode_with_verifier(
83 claim
84 .as_str()
85 .ok_or(TrustchainCRError::FailedToConvertToStr(claim.clone()))?,
86 &verifier,
87 )?;
88 Ok(payload)
89 }
90}
91
92pub fn josekit_to_ssi_jwk(key: &Jwk) -> Result<JWK, serde_json::Error> {
94 let key_as_str: &str = &serde_json::to_string(&key)?;
95 let ssi_key: JWK = serde_json::from_str(key_as_str)?;
96 Ok(ssi_key)
97}
98pub fn ssi_to_josekit_jwk(key: &JWK) -> Result<Jwk, serde_json::Error> {
100 let key_as_str: &str = &serde_json::to_string(&key)?;
101 let ssi_key: Jwk = serde_json::from_str(key_as_str)?;
102 Ok(ssi_key)
103}
104
105pub fn extract_key_ids_and_jwk(
107 document: &Document,
108) -> Result<HashMap<String, Jwk>, TrustchainCRError> {
109 let mut my_map = HashMap::<String, Jwk>::new();
110 if let Some(vms) = &document.verification_method {
111 for vm in vms {
124 if let VerificationMethod::Map(vm_map) = vm {
125 let key = vm_map
126 .get_jwk()
127 .map_err(|_| TrustchainCRError::MissingJWK)?;
128 let id = key
129 .thumbprint()
130 .map_err(|_| TrustchainCRError::MissingJWK)?;
131 let key_jose = ssi_to_josekit_jwk(&key).map_err(TrustchainCRError::Serde)?;
132 my_map.insert(id, key_jose);
133 }
134 }
135 }
136 Ok(my_map)
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142 use crate::data::{TEST_CANDIDATE_DDID_DOCUMENT, TEST_SIGNING_KEY_1, TEST_SIGNING_KEY_2};
143 #[test]
144 fn test_sign_encrypt_and_decrypt_verify() {
145 let entity = Entity {};
146 let mut payload = JwtPayload::new();
147 payload
148 .set_claim("test", Some(Value::from("This is a test claim.")))
149 .unwrap();
150 let secret_key_1: Jwk = serde_json::from_str(TEST_SIGNING_KEY_1).unwrap();
152 let secret_key_2: Jwk = serde_json::from_str(TEST_SIGNING_KEY_2).unwrap();
153 let public_key_1 = secret_key_1.to_public_key().unwrap();
154 let public_key_2 = secret_key_2.to_public_key().unwrap();
155 let signed_encrypted_payload = entity
156 .sign_and_encrypt_claim(&payload, &secret_key_1, &public_key_2)
157 .unwrap();
158 let decrypted_verified_payload = entity
160 .decrypt_and_verify(signed_encrypted_payload, &secret_key_2, &public_key_1)
161 .unwrap();
162 assert_eq!(
163 decrypted_verified_payload
164 .claim("test")
165 .unwrap()
166 .as_str()
167 .unwrap(),
168 "This is a test claim."
169 );
170 }
171
172 #[test]
173 fn test_extract_key_ids_and_jwk() {
174 let document: Document = serde_json::from_str(TEST_CANDIDATE_DDID_DOCUMENT).unwrap();
175 let key_ids_and_jwk = extract_key_ids_and_jwk(&document).unwrap();
176 assert_eq!(key_ids_and_jwk.len(), 2);
177 }
178}