From 41bc957eae9934e815cd8b7bf521ba422b878f12 Mon Sep 17 00:00:00 2001 From: Hermann Core Date: Mon, 9 Dec 2024 12:15:44 +0100 Subject: [PATCH 1/7] cleaning up the codebase --- Cargo.toml | 1 + .../did-utils/src/jwk/jwk.rs | 531 --------- .../did-utils/src/jwk/mod.rs | 489 +++++++- .../mediator-coordination/Cargo.toml | 2 + .../src/handler/midlw.rs | 208 ++-- .../mediator-coordination/src/handler/mod.rs | 4 +- .../src/handler/stateless.rs | 1016 +++++++---------- .../mediator-coordination/src/model/coord.rs | 4 +- .../mediator-coordination/src/model/mod.rs | 2 +- .../src/model/stateless/coord.rs | 38 +- .../src/model/stateless/dic.rs | 20 +- .../mediator-coordination/src/plugin.rs | 12 + .../src/did_rotation/did_rotation.rs | 324 ------ .../didcomm-messaging/src/did_rotation/mod.rs | 325 +++++- .../didcomm-messaging/src/midlw.rs | 2 +- 15 files changed, 1401 insertions(+), 1577 deletions(-) delete mode 100644 crates/web-plugins/didcomm-messaging/did-utils/src/jwk/jwk.rs delete mode 100644 crates/web-plugins/didcomm-messaging/src/did_rotation/did_rotation.rs diff --git a/Cargo.toml b/Cargo.toml index c8f8a93e..2a33a6ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,6 +78,7 @@ axum = "0.6.20" tokio = "1.30.0" tracing = "0.1.37" chrono = "0.4.26" +paste = "0.1" didcomm = "0.4.1" hyper = "0.14.27" lazy_static = "1.4.0" diff --git a/crates/web-plugins/didcomm-messaging/did-utils/src/jwk/jwk.rs b/crates/web-plugins/didcomm-messaging/did-utils/src/jwk/jwk.rs deleted file mode 100644 index 1749a38e..00000000 --- a/crates/web-plugins/didcomm-messaging/did-utils/src/jwk/jwk.rs +++ /dev/null @@ -1,531 +0,0 @@ -use crate::{ - crypto::ToPublic, - jwk::{Ec, Key, Oct, Okp, Parameters, Rsa, Secret}, -}; -extern crate alloc; -use serde::{Deserialize, Serialize}; - -/// A set of JSON Web Keys. -/// -/// This type is defined in [RFC7517 Section 5]. -/// -/// [RFC7517 Section 5]: https://datatracker.ietf.org/doc/html/rfc7517#section-5 -#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] -pub struct JwkSet { - /// The keys in the set. - pub keys: alloc::vec::Vec, -} - -/// A JSON Web Key. -/// -/// This type is defined in [RFC7517 Section 4]. -/// -/// [RFC7517 Section 4]: https://datatracker.ietf.org/doc/html/rfc7517#section-4 -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Eq)] -pub struct Jwk { - #[serde(flatten)] - pub key: Key, - /// The key parameters. - #[serde(flatten)] - pub prm: Parameters, -} - -impl ToPublic for Jwk { - fn to_public(&self) -> Self { - let public_key = match &self.key { - Key::Ec(ec) => Key::Ec(Ec { - crv: ec.crv, - x: ec.x.clone(), - y: ec.y.clone(), - d: None, - }), - Key::Rsa(rsa) => Key::Rsa(Rsa { - prv: None, - e: rsa.e.clone(), - n: rsa.n.clone(), - }), - Key::Oct(_oct) => Key::Oct(Oct { k: Secret::default() }), - Key::Okp(okp) => Key::Okp(Okp { - d: None, - crv: okp.crv, - x: okp.x.clone(), - }), - }; - - Jwk { - key: public_key, - prm: self.prm.clone(), - } - } -} - -#[cfg(test)] -mod rfc7517 { - use crate::jwk::prm::Signing; - use crate::jwk::{ec::*, jwk::*, prm::*, rsa::*}; - - #[test] - fn a1() { - let val = serde_json::json!({ - "keys": [ - { - "kty": "EC", - "crv": "P-256", - "x": "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", - "y": "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", - "use": "enc", - "kid": "1", - }, - { - "kty": "RSA", - "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw", - "e": "AQAB", - "alg": "RS256", - "kid": "2011-04-29", - } - ] - }); - - let jwk = JwkSet { - keys: vec![ - Jwk { - key: Key::Ec(Ec { - crv: EcCurves::P256, - d: None, - x: vec![ - 48, 160, 66, 76, 210, 28, 41, 68, 131, 138, 45, 117, 201, 43, 55, 231, 110, 162, 13, 159, 0, 137, 58, 59, 78, 238, 138, - 60, 10, 175, 236, 62, - ] - .into(), - y: vec![ - 224, 75, 101, 233, 36, 86, 217, 136, 139, 82, 179, 121, 189, 251, 213, 30, 232, 105, 239, 31, 15, 198, 91, 102, 89, 105, - 91, 108, 206, 8, 23, 35, - ] - .into(), - }), - prm: Parameters { - kid: Some("1".to_string()), - cls: Some(Class::Encryption), - ..Default::default() - }, - }, - Jwk { - key: Key::Rsa(Rsa { - prv: None, - e: vec![1, 0, 1].into(), - n: vec![ - 210, 252, 123, 106, 10, 30, 108, 103, 16, 74, 235, 143, 136, 178, 87, 102, 155, 77, 246, 121, 221, 173, 9, 155, 92, 74, - 108, 217, 168, 128, 21, 181, 161, 51, 191, 11, 133, 108, 120, 113, 182, 223, 0, 11, 85, 79, 206, 179, 194, 237, 81, 43, - 182, 143, 20, 92, 110, 132, 52, 117, 47, 171, 82, 161, 207, 193, 36, 64, 143, 121, 181, 138, 69, 120, 193, 100, 40, 133, - 87, 137, 247, 162, 73, 227, 132, 203, 45, 159, 174, 45, 103, 253, 150, 251, 146, 108, 25, 142, 7, 115, 153, 253, 200, 21, - 192, 175, 9, 125, 222, 90, 173, 239, 244, 77, 231, 14, 130, 127, 72, 120, 67, 36, 57, 191, 238, 185, 96, 104, 208, 71, - 79, 197, 13, 109, 144, 191, 58, 152, 223, 175, 16, 64, 200, 156, 2, 214, 146, 171, 59, 60, 40, 150, 96, 157, 134, 253, - 115, 183, 116, 206, 7, 64, 100, 124, 238, 234, 163, 16, 189, 18, 249, 133, 168, 235, 159, 89, 253, 212, 38, 206, 165, - 178, 18, 15, 79, 42, 52, 188, 171, 118, 75, 126, 108, 84, 214, 132, 2, 56, 188, 196, 5, 135, 165, 158, 102, 237, 31, 51, - 137, 69, 119, 99, 92, 71, 10, 247, 92, 249, 44, 32, 209, 218, 67, 225, 191, 196, 25, 226, 34, 166, 240, 208, 187, 53, - 140, 94, 56, 249, 203, 5, 10, 234, 254, 144, 72, 20, 241, 172, 26, 164, 156, 202, 158, 160, 202, 131, - ] - .into(), - }), - prm: Parameters { - alg: Some(Signing::Rs256.into()), - kid: Some("2011-04-29".to_string()), - ..Default::default() - }, - }, - ], - }; - - assert_eq!(jwk, serde_json::from_value(val.clone()).unwrap()); - assert_eq!(val, serde_json::to_value(&jwk).unwrap()); - - #[cfg(feature = "p256")] - if let Key::Ec(key) = &jwk.keys[0].key { - let pk = p256::PublicKey::try_from(key).unwrap(); - assert_eq!(key, &pk.into()); - } else { - unreachable!() - } - - #[cfg(feature = "rsa")] - if let Key::Rsa(key) = &jwk.keys[1].key { - let pk = ::rsa::RsaPublicKey::try_from(key).unwrap(); - assert_eq!(key, &pk.into()); - } else { - unreachable!() - } - } - - #[test] - fn a2() { - let val = serde_json::json!({ - "keys": [ - { - "kty":"EC", - "crv":"P-256", - "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", - "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", - "d":"870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE", - "use":"enc", - "kid":"1" - }, - - { - "kty":"RSA", - "n":"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw", - "e":"AQAB", - "d":"X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqijwp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBznbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFzme1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q", - "p":"83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPVnwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqVWlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs", - "q":"3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyumqjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgxkIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk", - "dp":"G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oimYwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_NmtuYZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0", - "dq":"s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUUvMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk", - "qi":"GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzgUIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rxyR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU", - "alg":"RS256", - "kid":"2011-04-29" - } - ] - }); - - let jwk = JwkSet { - keys: vec![ - Jwk { - key: Key::Ec(Ec { - crv: EcCurves::P256, - d: Some( - vec![ - 243, 189, 12, 7, 168, 31, 185, 50, 120, 30, 213, 39, 82, 246, 12, 200, 154, 107, 229, 229, 25, 52, 254, 1, 147, 141, - 219, 85, 216, 247, 120, 1, - ] - .into(), - ), - x: vec![ - 48, 160, 66, 76, 210, 28, 41, 68, 131, 138, 45, 117, 201, 43, 55, 231, 110, 162, 13, 159, 0, 137, 58, 59, 78, 238, 138, - 60, 10, 175, 236, 62, - ] - .into(), - y: vec![ - 224, 75, 101, 233, 36, 86, 217, 136, 139, 82, 179, 121, 189, 251, 213, 30, 232, 105, 239, 31, 15, 198, 91, 102, 89, 105, - 91, 108, 206, 8, 23, 35, - ] - .into(), - }), - prm: Parameters { - kid: Some("1".to_string()), - cls: Some(Class::Encryption), - ..Default::default() - }, - }, - Jwk { - key: Key::Rsa(Rsa { - e: vec![1, 0, 1].into(), - n: vec![ - 210, 252, 123, 106, 10, 30, 108, 103, 16, 74, 235, 143, 136, 178, 87, 102, 155, 77, 246, 121, 221, 173, 9, 155, 92, 74, - 108, 217, 168, 128, 21, 181, 161, 51, 191, 11, 133, 108, 120, 113, 182, 223, 0, 11, 85, 79, 206, 179, 194, 237, 81, 43, - 182, 143, 20, 92, 110, 132, 52, 117, 47, 171, 82, 161, 207, 193, 36, 64, 143, 121, 181, 138, 69, 120, 193, 100, 40, 133, - 87, 137, 247, 162, 73, 227, 132, 203, 45, 159, 174, 45, 103, 253, 150, 251, 146, 108, 25, 142, 7, 115, 153, 253, 200, 21, - 192, 175, 9, 125, 222, 90, 173, 239, 244, 77, 231, 14, 130, 127, 72, 120, 67, 36, 57, 191, 238, 185, 96, 104, 208, 71, - 79, 197, 13, 109, 144, 191, 58, 152, 223, 175, 16, 64, 200, 156, 2, 214, 146, 171, 59, 60, 40, 150, 96, 157, 134, 253, - 115, 183, 116, 206, 7, 64, 100, 124, 238, 234, 163, 16, 189, 18, 249, 133, 168, 235, 159, 89, 253, 212, 38, 206, 165, - 178, 18, 15, 79, 42, 52, 188, 171, 118, 75, 126, 108, 84, 214, 132, 2, 56, 188, 196, 5, 135, 165, 158, 102, 237, 31, 51, - 137, 69, 119, 99, 92, 71, 10, 247, 92, 249, 44, 32, 209, 218, 67, 225, 191, 196, 25, 226, 34, 166, 240, 208, 187, 53, - 140, 94, 56, 249, 203, 5, 10, 234, 254, 144, 72, 20, 241, 172, 26, 164, 156, 202, 158, 160, 202, 131, - ] - .into(), - prv: Some(RsaPrivate { - d: vec![ - 95, 135, 19, 181, 226, 88, 254, 9, 248, 21, 131, 236, 92, 31, 43, 117, 120, 177, 230, 252, 44, 131, 81, 75, 55, 145, - 55, 17, 161, 186, 68, 154, 21, 31, 225, 203, 44, 160, 253, 51, 183, 113, 230, 138, 59, 25, 68, 100, 157, 200, 103, - 173, 28, 30, 82, 64, 187, 133, 62, 95, 36, 179, 52, 89, 177, 64, 40, 210, 214, 99, 107, 239, 236, 30, 141, 169, 116, - 179, 82, 252, 83, 211, 246, 18, 126, 168, 163, 194, 157, 209, 79, 57, 65, 104, 44, 86, 167, 135, 104, 22, 78, 77, - 218, 143, 6, 203, 249, 199, 52, 170, 232, 0, 50, 36, 39, 142, 169, 69, 74, 33, 177, 124, 176, 109, 23, 128, 117, 134, - 140, 192, 91, 61, 182, 255, 29, 253, 195, 213, 99, 120, 180, 237, 173, 237, 240, 195, 122, 76, 220, 38, 209, 212, - 154, 194, 111, 111, 227, 181, 34, 10, 93, 210, 147, 150, 98, 27, 188, 104, 140, 242, 238, 226, 198, 224, 213, 77, - 163, 199, 130, 1, 76, 208, 115, 157, 178, 82, 204, 81, 202, 235, 168, 211, 241, 184, 36, 186, 171, 36, 208, 104, 236, - 144, 50, 100, 215, 214, 120, 171, 8, 240, 110, 201, 231, 226, 61, 150, 6, 40, 183, 68, 191, 148, 179, 105, 70, 86, - 70, 60, 126, 65, 115, 153, 237, 115, 208, 118, 200, 145, 252, 244, 99, 169, 170, 156, 230, 45, 169, 205, 23, 226, 55, - 220, 42, 128, 2, 241, - ] - .into(), - - opt: Some(RsaOptional { - p: vec![ - 243, 120, 190, 236, 139, 204, 25, 122, 12, 92, 43, 36, 191, 189, 211, 42, 191, 58, 223, 177, 98, 59, 182, 118, - 239, 59, 252, 162, 62, 169, 109, 101, 16, 200, 179, 208, 5, 12, 109, 61, 89, 240, 15, 109, 17, 251, 173, 30, 76, - 57, 131, 218, 232, 231, 50, 222, 79, 162, 163, 43, 155, 196, 95, 152, 216, 85, 88, 59, 99, 140, 201, 130, 50, 51, - 169, 73, 120, 156, 20, 120, 251, 92, 235, 149, 33, 132, 50, 169, 85, 165, 88, 72, 122, 116, 221, 250, 25, 86, 88, - 147, 221, 205, 240, 23, 61, 189, 142, 53, 199, 47, 1, 245, 28, 243, 56, 101, 80, 205, 123, 205, 18, 249, 251, 59, - 73, 213, 109, 251, - ] - .into(), - q: vec![ - 221, 215, 206, 71, 215, 46, 98, 175, 180, 75, 233, 164, 20, 188, 224, 34, 216, 12, 17, 241, 115, 7, 106, 183, - 133, 103, 161, 50, 225, 180, 160, 43, 170, 157, 189, 239, 161, 178, 242, 186, 106, 163, 85, 148, 14, 213, 210, - 43, 119, 8, 19, 156, 39, 105, 99, 48, 92, 57, 245, 185, 175, 126, 244, 0, 85, 227, 137, 103, 237, 252, 209, 132, - 138, 139, 232, 158, 44, 225, 42, 154, 61, 85, 84, 187, 241, 60, 197, 131, 25, 8, 118, 183, 156, 69, 236, 236, - 103, 237, 100, 97, 223, 236, 214, 160, 219, 198, 217, 3, 18, 7, 192, 33, 48, 6, 244, 181, 39, 0, 59, 167, 226, - 242, 28, 111, 172, 158, 151, 25, - ] - .into(), - dp: vec![ - 27, 139, 15, 94, 71, 58, 97, 175, 114, 242, 130, 86, 247, 242, 11, 143, 140, 110, 166, 155, 180, 151, 56, 191, - 31, 181, 83, 145, 47, 49, 143, 148, 157, 95, 119, 40, 19, 74, 34, 153, 140, 49, 34, 45, 158, 153, 48, 46, 123, - 69, 14, 107, 151, 105, 128, 81, 178, 4, 158, 28, 242, 212, 54, 84, 94, 52, 217, 116, 110, 128, 160, 211, 63, 198, - 164, 98, 17, 104, 230, 208, 0, 239, 180, 30, 252, 217, 173, 185, 134, 92, 220, 45, 230, 220, 141, 184, 27, 97, - 175, 71, 155, 18, 15, 21, 50, 0, 221, 179, 171, 194, 223, 159, 209, 20, 154, 206, 171, 99, 115, 155, 241, 135, - 162, 42, 68, 226, 6, 61, - ] - .into(), - dq: vec![ - 179, 217, 64, 31, 215, 224, 128, 27, 40, 21, 31, 14, 105, 205, 145, 252, 77, 160, 195, 111, 54, 173, 61, 164, 24, - 224, 33, 188, 137, 101, 17, 49, 53, 121, 250, 192, 234, 27, 148, 82, 243, 31, 5, 195, 41, 159, 201, 106, 121, - 110, 175, 207, 57, 216, 99, 148, 146, 64, 94, 233, 49, 208, 191, 106, 2, 55, 156, 111, 8, 110, 157, 65, 81, 189, - 9, 82, 42, 218, 68, 218, 148, 124, 184, 92, 65, 191, 221, 244, 97, 120, 14, 30, 222, 239, 133, 155, 70, 202, 27, - 70, 137, 238, 141, 54, 13, 215, 16, 154, 63, 164, 206, 235, 88, 239, 90, 181, 254, 47, 95, 45, 197, 124, 56, 247, - 132, 63, 114, 9, - ] - .into(), - qi: vec![ - 27, 35, 63, 167, 162, 107, 95, 36, 162, 207, 91, 104, 22, 2, 155, 89, 95, 137, 116, 141, 227, 67, 140, 169, 187, - 218, 219, 49, 108, 119, 173, 2, 65, 126, 107, 116, 22, 134, 51, 129, 66, 25, 17, 81, 68, 112, 234, 176, 122, 100, - 77, 243, 92, 232, 12, 6, 154, 248, 25, 52, 41, 99, 70, 14, 50, 71, 100, 55, 67, 152, 88, 86, 220, 3, 123, 148, - 143, 169, 187, 25, 63, 152, 118, 70, 39, 93, 107, 199, 36, 124, 59, 158, 87, 45, 39, 183, 72, 249, 145, 124, 172, - 25, 35, 172, 148, 219, 134, 113, 189, 2, 133, 96, 139, 93, 149, 213, 10, 27, 51, 186, 33, 174, 179, 76, 168, 64, - 85, 21, - ] - .into(), - oth: vec![], - }), - }), - }), - prm: Parameters { - alg: Some(Signing::Rs256.into()), - kid: Some("2011-04-29".to_string()), - ..Default::default() - }, - }, - ], - }; - - assert_eq!(jwk, serde_json::from_value(val.clone()).unwrap()); - assert_eq!(val, serde_json::to_value(&jwk).unwrap()); - - #[cfg(feature = "p256")] - if let Key::Ec(key) = &jwk.keys[0].key { - let sk = p256::SecretKey::try_from(key).unwrap(); - assert_eq!(key, &sk.into()); - } else { - unreachable!() - } - - #[cfg(feature = "rsa")] - if let Key::Rsa(key) = &jwk.keys[1].key { - let pk = ::rsa::RsaPrivateKey::try_from(key).unwrap(); - // FIXME: work around the serialization asymmetry. - let mut k: Rsa = pk.into(); - k.prv.as_mut().unwrap().opt = key.prv.as_ref().unwrap().opt.clone(); - assert_eq!(key, &k); - } else { - unreachable!() - } - } - - #[test] - fn b() { - let val = serde_json::json!({ - "kty":"RSA", - "use":"sig", - "kid":"1b94c", - "n":"vrjOfz9Ccdgx5nQudyhdoR17V-IubWMeOZCwX_jj0hgAsz2J_pqYW08PLbK_PdiVGKPrqzmDIsLI7sA25VEnHU1uCLNwBuUiCO11_-7dYbsr4iJmG0Qu2j8DsVyT1azpJC_NG84Ty5KKthuCaPod7iI7w0LK9orSMhBEwwZDCxTWq4aYWAchc8t-emd9qOvWtVMDC2BXksRngh6X5bUYLy6AyHKvj-nUy1wgzjYQDwHMTplCoLtU-o-8SNnZ1tmRoGE9uJkBLdh5gFENabWnU5m1ZqZPdwS-qo-meMvVfJb6jJVWRpl2SUtCnYG2C32qvbWbjZ_jBPD5eunqsIo1vQ", - "e":"AQAB", - "x5c": [ - "MIIDQjCCAiqgAwIBAgIGATz/FuLiMA0GCSqGSIb3DQEBBQUAMGIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYDVQQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1wYmVsbDAeFw0xMzAyMjEyMzI5MTVaFw0xODA4MTQyMjI5MTVaMGIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYDVQQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1wYmVsbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL64zn8/QnHYMeZ0LncoXaEde1fiLm1jHjmQsF/449IYALM9if6amFtPDy2yvz3YlRij66s5gyLCyO7ANuVRJx1NbgizcAblIgjtdf/u3WG7K+IiZhtELto/A7Fck9Ws6SQvzRvOE8uSirYbgmj6He4iO8NCyvaK0jIQRMMGQwsU1quGmFgHIXPLfnpnfajr1rVTAwtgV5LEZ4Iel+W1GC8ugMhyr4/p1MtcIM42EA8BzE6ZQqC7VPqPvEjZ2dbZkaBhPbiZAS3YeYBRDWm1p1OZtWamT3cEvqqPpnjL1XyW+oyVVkaZdklLQp2Btgt9qr21m42f4wTw+Xrp6rCKNb0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAh8zGlfSlcI0o3rYDPBB07aXNswb4ECNIKG0CETTUxmXl9KUL+9gGlqCz5iWLOgWsnrcKcY0vXPG9J1r9AqBNTqNgHq2G03X09266X5CpOe1zFo+Owb1zxtp3PehFdfQJ610CDLEaS9V9Rqp17hCyybEpOGVwe8fnk+fbEL2Bo3UPGrpsHzUoaGpDftmWssZkhpBJKVMJyf/RuP2SmmaIzmnw9JiSlYhzo4tpzd5rFXhjRbg4zW9C+2qok+2+qDM1iJ684gPHMIY8aLWrdgQTxkumGmTqgawR+N5MDtdPTEQ0XfIBc2cJEUyMTY5MPvACWpkA6SdS4xSvdXK3IVfOWA==" - ] - }); - - let jwk = Jwk { - key: Key::Rsa(Rsa { - prv: None, - e: vec![1, 0, 1].into(), - n: vec![ - 190, 184, 206, 127, 63, 66, 113, 216, 49, 230, 116, 46, 119, 40, 93, 161, 29, 123, 87, 226, 46, 109, 99, 30, 57, 144, 176, 95, - 248, 227, 210, 24, 0, 179, 61, 137, 254, 154, 152, 91, 79, 15, 45, 178, 191, 61, 216, 149, 24, 163, 235, 171, 57, 131, 34, 194, - 200, 238, 192, 54, 229, 81, 39, 29, 77, 110, 8, 179, 112, 6, 229, 34, 8, 237, 117, 255, 238, 221, 97, 187, 43, 226, 34, 102, 27, - 68, 46, 218, 63, 3, 177, 92, 147, 213, 172, 233, 36, 47, 205, 27, 206, 19, 203, 146, 138, 182, 27, 130, 104, 250, 29, 238, 34, - 59, 195, 66, 202, 246, 138, 210, 50, 16, 68, 195, 6, 67, 11, 20, 214, 171, 134, 152, 88, 7, 33, 115, 203, 126, 122, 103, 125, - 168, 235, 214, 181, 83, 3, 11, 96, 87, 146, 196, 103, 130, 30, 151, 229, 181, 24, 47, 46, 128, 200, 114, 175, 143, 233, 212, 203, - 92, 32, 206, 54, 16, 15, 1, 204, 78, 153, 66, 160, 187, 84, 250, 143, 188, 72, 217, 217, 214, 217, 145, 160, 97, 61, 184, 153, 1, - 45, 216, 121, 128, 81, 13, 105, 181, 167, 83, 153, 181, 102, 166, 79, 119, 4, 190, 170, 143, 166, 120, 203, 213, 124, 150, 250, - 140, 149, 86, 70, 153, 118, 73, 75, 66, 157, 129, 182, 11, 125, 170, 189, 181, 155, 141, 159, 227, 4, 240, 249, 122, 233, 234, - 176, 138, 53, 189, - ] - .into(), - }), - prm: Parameters { - kid: Some("1b94c".to_string()), - cls: Some(Class::Signing), - x5c: Some(vec![From::from(vec![ - 48, 130, 3, 66, 48, 130, 2, 42, 160, 3, 2, 1, 2, 2, 6, 1, 60, 255, 22, 226, 226, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, - 5, 5, 0, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, 4, 8, 19, 2, 67, 79, 49, 15, 48, 13, 6, - 3, 85, 4, 7, 19, 6, 68, 101, 110, 118, 101, 114, 49, 28, 48, 26, 6, 3, 85, 4, 10, 19, 19, 80, 105, 110, 103, 32, 73, 100, 101, - 110, 116, 105, 116, 121, 32, 67, 111, 114, 112, 46, 49, 23, 48, 21, 6, 3, 85, 4, 3, 19, 14, 66, 114, 105, 97, 110, 32, 67, 97, - 109, 112, 98, 101, 108, 108, 48, 30, 23, 13, 49, 51, 48, 50, 50, 49, 50, 51, 50, 57, 49, 53, 90, 23, 13, 49, 56, 48, 56, 49, 52, - 50, 50, 50, 57, 49, 53, 90, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, 4, 8, 19, 2, 67, 79, - 49, 15, 48, 13, 6, 3, 85, 4, 7, 19, 6, 68, 101, 110, 118, 101, 114, 49, 28, 48, 26, 6, 3, 85, 4, 10, 19, 19, 80, 105, 110, 103, - 32, 73, 100, 101, 110, 116, 105, 116, 121, 32, 67, 111, 114, 112, 46, 49, 23, 48, 21, 6, 3, 85, 4, 3, 19, 14, 66, 114, 105, 97, - 110, 32, 67, 97, 109, 112, 98, 101, 108, 108, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, - 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 190, 184, 206, 127, 63, 66, 113, 216, 49, 230, 116, 46, 119, 40, 93, 161, 29, 123, 87, - 226, 46, 109, 99, 30, 57, 144, 176, 95, 248, 227, 210, 24, 0, 179, 61, 137, 254, 154, 152, 91, 79, 15, 45, 178, 191, 61, 216, - 149, 24, 163, 235, 171, 57, 131, 34, 194, 200, 238, 192, 54, 229, 81, 39, 29, 77, 110, 8, 179, 112, 6, 229, 34, 8, 237, 117, 255, - 238, 221, 97, 187, 43, 226, 34, 102, 27, 68, 46, 218, 63, 3, 177, 92, 147, 213, 172, 233, 36, 47, 205, 27, 206, 19, 203, 146, - 138, 182, 27, 130, 104, 250, 29, 238, 34, 59, 195, 66, 202, 246, 138, 210, 50, 16, 68, 195, 6, 67, 11, 20, 214, 171, 134, 152, - 88, 7, 33, 115, 203, 126, 122, 103, 125, 168, 235, 214, 181, 83, 3, 11, 96, 87, 146, 196, 103, 130, 30, 151, 229, 181, 24, 47, - 46, 128, 200, 114, 175, 143, 233, 212, 203, 92, 32, 206, 54, 16, 15, 1, 204, 78, 153, 66, 160, 187, 84, 250, 143, 188, 72, 217, - 217, 214, 217, 145, 160, 97, 61, 184, 153, 1, 45, 216, 121, 128, 81, 13, 105, 181, 167, 83, 153, 181, 102, 166, 79, 119, 4, 190, - 170, 143, 166, 120, 203, 213, 124, 150, 250, 140, 149, 86, 70, 153, 118, 73, 75, 66, 157, 129, 182, 11, 125, 170, 189, 181, 155, - 141, 159, 227, 4, 240, 249, 122, 233, 234, 176, 138, 53, 189, 2, 3, 1, 0, 1, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, - 0, 3, 130, 1, 1, 0, 135, 204, 198, 149, 244, 165, 112, 141, 40, 222, 182, 3, 60, 16, 116, 237, 165, 205, 179, 6, 248, 16, 35, 72, - 40, 109, 2, 17, 52, 212, 198, 101, 229, 244, 165, 11, 251, 216, 6, 150, 160, 179, 230, 37, 139, 58, 5, 172, 158, 183, 10, 113, - 141, 47, 92, 241, 189, 39, 90, 253, 2, 160, 77, 78, 163, 96, 30, 173, 134, 211, 117, 244, 247, 110, 186, 95, 144, 169, 57, 237, - 115, 22, 143, 142, 193, 189, 115, 198, 218, 119, 61, 232, 69, 117, 244, 9, 235, 93, 2, 12, 177, 26, 75, 213, 125, 70, 170, 117, - 238, 16, 178, 201, 177, 41, 56, 101, 112, 123, 199, 231, 147, 231, 219, 16, 189, 129, 163, 117, 15, 26, 186, 108, 31, 53, 40, - 104, 106, 67, 126, 217, 150, 178, 198, 100, 134, 144, 73, 41, 83, 9, 201, 255, 209, 184, 253, 146, 154, 102, 136, 206, 105, 240, - 244, 152, 146, 149, 136, 115, 163, 139, 105, 205, 222, 107, 21, 120, 99, 69, 184, 56, 205, 111, 66, 251, 106, 168, 147, 237, 190, - 168, 51, 53, 136, 158, 188, 226, 3, 199, 48, 134, 60, 104, 181, 171, 118, 4, 19, 198, 75, 166, 26, 100, 234, 129, 172, 17, 248, - 222, 76, 14, 215, 79, 76, 68, 52, 93, 242, 1, 115, 103, 9, 17, 76, 140, 77, 142, 76, 62, 240, 2, 90, 153, 0, 233, 39, 82, 227, - 20, 175, 117, 114, 183, 33, 87, 206, 88, - ])]), - ..Default::default() - }, - }; - - assert_eq!(jwk, serde_json::from_value(val.clone()).unwrap()); - assert_eq!(val, serde_json::to_value(&jwk).unwrap()); - - #[cfg(feature = "rsa")] - if let Key::Rsa(key) = &jwk.key { - let pk = ::rsa::RsaPublicKey::try_from(key).unwrap(); - assert_eq!(key, &pk.into()); - } else { - unreachable!() - } - } -} - -#[cfg(test)] -mod rfc8037 { - use crate::jwk::{jwk::*, okp::*, prm::*}; - #[test] - fn a1() { - let val = serde_json::json!({ - "kty":"OKP", - "crv":"Ed25519", - "d":"nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A", - "x":"11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo" - }); - - let jwk = Jwk { - key: Key::Okp(Okp { - crv: OkpCurves::Ed25519, - d: Some( - vec![ - 157, 97, 177, 157, 239, 253, 90, 96, 186, 132, 74, 244, 146, 236, 44, 196, 68, 73, 197, 105, 123, 50, 105, 25, 112, 59, 172, - 3, 28, 174, 127, 96, - ] - .into(), - ), - x: vec![ - 215, 90, 152, 1, 130, 177, 10, 183, 213, 75, 254, 211, 201, 100, 7, 58, 14, 225, 114, 243, 218, 166, 35, 37, 175, 2, 26, 104, - 247, 7, 81, 26, - ] - .into(), - }), - prm: Parameters::default(), - }; - - assert_eq!(jwk, serde_json::from_value(val.clone()).unwrap()); - assert_eq!(val, serde_json::to_value(jwk).unwrap()); - } - - #[test] - fn a2() { - let val = serde_json::json!({ - "kty":"OKP", - "crv":"Ed25519", - "x":"11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo" - }); - - let jwk = Jwk { - key: Key::Okp(Okp { - crv: OkpCurves::Ed25519, - d: None, - x: vec![ - 215, 90, 152, 1, 130, 177, 10, 183, 213, 75, 254, 211, 201, 100, 7, 58, 14, 225, 114, 243, 218, 166, 35, 37, 175, 2, 26, 104, - 247, 7, 81, 26, - ] - .into(), - }), - prm: Parameters::default(), - }; - - assert_eq!(jwk, serde_json::from_value(val.clone()).unwrap()); - assert_eq!(val, serde_json::to_value(jwk).unwrap()); - } - - #[test] - fn a6() { - let val = serde_json::json!({ - "kty":"OKP", - "crv":"X25519", - "kid":"Bob", - "x":"3p7bfXt9wbTTW2HC7OQ1Nz-DQ8hbeGdNrfx-FG-IK08" - }); - - let jwk = Jwk { - key: Key::Okp(Okp { - crv: OkpCurves::X25519, - d: None, - x: vec![ - 222, 158, 219, 125, 123, 125, 193, 180, 211, 91, 97, 194, 236, 228, 53, 55, 63, 131, 67, 200, 91, 120, 103, 77, 173, 252, 126, - 20, 111, 136, 43, 79, - ] - .into(), - }), - prm: Parameters { - kid: Some("Bob".to_string()), - ..Default::default() - }, - }; - - assert_eq!(jwk, serde_json::from_value(val.clone()).unwrap()); - assert_eq!(val, serde_json::to_value(jwk).unwrap()); - } - - #[test] - fn a7() { - let val = serde_json::json!({ - "kty": "OKP", - "crv": "X448", - "kid": "Dave", - "x": "PreoKbDNIPW8_AtZm2_sz22kYnEHvbDU80W0MCfYuXL8PjT7QjKhPKcG3LV67D2uB73BxnvzNgk" - }); - - let jwk = Jwk { - key: Key::Okp(Okp { - crv: OkpCurves::X448, - d: None, - x: vec![ - 62, 183, 168, 41, 176, 205, 32, 245, 188, 252, 11, 89, 155, 111, 236, 207, 109, 164, 98, 113, 7, 189, 176, 212, 243, 69, 180, 48, - 39, 216, 185, 114, 252, 62, 52, 251, 66, 50, 161, 60, 167, 6, 220, 181, 122, 236, 61, 174, 7, 189, 193, 198, 123, 243, 54, 9, - ] - .into(), - }), - prm: Parameters { - kid: Some("Dave".to_string()), - ..Default::default() - }, - }; - - assert_eq!(jwk, serde_json::from_value(val.clone()).unwrap()); - assert_eq!(val, serde_json::to_value(jwk).unwrap()); - } -} diff --git a/crates/web-plugins/didcomm-messaging/did-utils/src/jwk/mod.rs b/crates/web-plugins/didcomm-messaging/did-utils/src/jwk/mod.rs index 0f8e2481..99a3908b 100644 --- a/crates/web-plugins/didcomm-messaging/did-utils/src/jwk/mod.rs +++ b/crates/web-plugins/didcomm-messaging/did-utils/src/jwk/mod.rs @@ -33,7 +33,6 @@ mod bytes; mod ec; -mod jwk; mod key; mod oct; mod okp; @@ -44,10 +43,496 @@ mod secret; // Re-exports pub use bytes::Bytes; pub use ec::{Ec, EcCurves}; -pub use jwk::{Jwk, JwkSet}; pub use key::Key; pub use oct::Oct; pub use okp::{Okp, OkpCurves}; pub use prm::Parameters; pub use rsa::Rsa; pub use secret::Secret; + +use crate::crypto::ToPublic; +extern crate alloc; +use serde::{Deserialize, Serialize}; + +/// A set of JSON Web Keys. +/// +/// This type is defined in [RFC7517 Section 5]. +/// +/// [RFC7517 Section 5]: https://datatracker.ietf.org/doc/html/rfc7517#section-5 +#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +pub struct JwkSet { + /// The keys in the set. + pub keys: alloc::vec::Vec, +} + +/// A JSON Web Key. +/// +/// This type is defined in [RFC7517 Section 4]. +/// +/// [RFC7517 Section 4]: https://datatracker.ietf.org/doc/html/rfc7517#section-4 +#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Eq)] +pub struct Jwk { + #[serde(flatten)] + pub key: Key, + /// The key parameters. + #[serde(flatten)] + pub prm: Parameters, +} + +impl ToPublic for Jwk { + fn to_public(&self) -> Self { + let public_key = match &self.key { + Key::Ec(ec) => Key::Ec(Ec { + crv: ec.crv, + x: ec.x.clone(), + y: ec.y.clone(), + d: None, + }), + Key::Rsa(rsa) => Key::Rsa(Rsa { + prv: None, + e: rsa.e.clone(), + n: rsa.n.clone(), + }), + Key::Oct(_oct) => Key::Oct(Oct { k: Secret::default() }), + Key::Okp(okp) => Key::Okp(Okp { + d: None, + crv: okp.crv, + x: okp.x.clone(), + }), + }; + + Jwk { + key: public_key, + prm: self.prm.clone(), + } + } +} + +#[cfg(test)] +mod rfc7517 { + use crate::jwk::prm::Signing; + use crate::jwk::{ec::*, prm::*, rsa::*, Jwk, JwkSet, Key}; + + #[test] + fn a1() { + let val = serde_json::json!({ + "keys": [ + { + "kty": "EC", + "crv": "P-256", + "x": "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", + "y": "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", + "use": "enc", + "kid": "1", + }, + { + "kty": "RSA", + "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw", + "e": "AQAB", + "alg": "RS256", + "kid": "2011-04-29", + } + ] + }); + + let jwk = JwkSet { + keys: vec![ + Jwk { + key: Key::Ec(Ec { + crv: EcCurves::P256, + d: None, + x: vec![ + 48, 160, 66, 76, 210, 28, 41, 68, 131, 138, 45, 117, 201, 43, 55, 231, 110, 162, 13, 159, 0, 137, 58, 59, 78, 238, 138, + 60, 10, 175, 236, 62, + ] + .into(), + y: vec![ + 224, 75, 101, 233, 36, 86, 217, 136, 139, 82, 179, 121, 189, 251, 213, 30, 232, 105, 239, 31, 15, 198, 91, 102, 89, 105, + 91, 108, 206, 8, 23, 35, + ] + .into(), + }), + prm: Parameters { + kid: Some("1".to_string()), + cls: Some(Class::Encryption), + ..Default::default() + }, + }, + Jwk { + key: Key::Rsa(Rsa { + prv: None, + e: vec![1, 0, 1].into(), + n: vec![ + 210, 252, 123, 106, 10, 30, 108, 103, 16, 74, 235, 143, 136, 178, 87, 102, 155, 77, 246, 121, 221, 173, 9, 155, 92, 74, + 108, 217, 168, 128, 21, 181, 161, 51, 191, 11, 133, 108, 120, 113, 182, 223, 0, 11, 85, 79, 206, 179, 194, 237, 81, 43, + 182, 143, 20, 92, 110, 132, 52, 117, 47, 171, 82, 161, 207, 193, 36, 64, 143, 121, 181, 138, 69, 120, 193, 100, 40, 133, + 87, 137, 247, 162, 73, 227, 132, 203, 45, 159, 174, 45, 103, 253, 150, 251, 146, 108, 25, 142, 7, 115, 153, 253, 200, 21, + 192, 175, 9, 125, 222, 90, 173, 239, 244, 77, 231, 14, 130, 127, 72, 120, 67, 36, 57, 191, 238, 185, 96, 104, 208, 71, + 79, 197, 13, 109, 144, 191, 58, 152, 223, 175, 16, 64, 200, 156, 2, 214, 146, 171, 59, 60, 40, 150, 96, 157, 134, 253, + 115, 183, 116, 206, 7, 64, 100, 124, 238, 234, 163, 16, 189, 18, 249, 133, 168, 235, 159, 89, 253, 212, 38, 206, 165, + 178, 18, 15, 79, 42, 52, 188, 171, 118, 75, 126, 108, 84, 214, 132, 2, 56, 188, 196, 5, 135, 165, 158, 102, 237, 31, 51, + 137, 69, 119, 99, 92, 71, 10, 247, 92, 249, 44, 32, 209, 218, 67, 225, 191, 196, 25, 226, 34, 166, 240, 208, 187, 53, + 140, 94, 56, 249, 203, 5, 10, 234, 254, 144, 72, 20, 241, 172, 26, 164, 156, 202, 158, 160, 202, 131, + ] + .into(), + }), + prm: Parameters { + alg: Some(Signing::Rs256.into()), + kid: Some("2011-04-29".to_string()), + ..Default::default() + }, + }, + ], + }; + + assert_eq!(jwk, serde_json::from_value(val.clone()).unwrap()); + assert_eq!(val, serde_json::to_value(&jwk).unwrap()); + } + + #[test] + fn a2() { + let val = serde_json::json!({ + "keys": [ + { + "kty":"EC", + "crv":"P-256", + "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", + "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", + "d":"870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE", + "use":"enc", + "kid":"1" + }, + + { + "kty":"RSA", + "n":"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw", + "e":"AQAB", + "d":"X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqijwp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBznbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFzme1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q", + "p":"83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPVnwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqVWlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs", + "q":"3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyumqjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgxkIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk", + "dp":"G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oimYwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_NmtuYZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0", + "dq":"s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUUvMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk", + "qi":"GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzgUIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rxyR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU", + "alg":"RS256", + "kid":"2011-04-29" + } + ] + }); + + let jwk = JwkSet { + keys: vec![ + Jwk { + key: Key::Ec(Ec { + crv: EcCurves::P256, + d: Some( + vec![ + 243, 189, 12, 7, 168, 31, 185, 50, 120, 30, 213, 39, 82, 246, 12, 200, 154, 107, 229, 229, 25, 52, 254, 1, 147, 141, + 219, 85, 216, 247, 120, 1, + ] + .into(), + ), + x: vec![ + 48, 160, 66, 76, 210, 28, 41, 68, 131, 138, 45, 117, 201, 43, 55, 231, 110, 162, 13, 159, 0, 137, 58, 59, 78, 238, 138, + 60, 10, 175, 236, 62, + ] + .into(), + y: vec![ + 224, 75, 101, 233, 36, 86, 217, 136, 139, 82, 179, 121, 189, 251, 213, 30, 232, 105, 239, 31, 15, 198, 91, 102, 89, 105, + 91, 108, 206, 8, 23, 35, + ] + .into(), + }), + prm: Parameters { + kid: Some("1".to_string()), + cls: Some(Class::Encryption), + ..Default::default() + }, + }, + Jwk { + key: Key::Rsa(Rsa { + e: vec![1, 0, 1].into(), + n: vec![ + 210, 252, 123, 106, 10, 30, 108, 103, 16, 74, 235, 143, 136, 178, 87, 102, 155, 77, 246, 121, 221, 173, 9, 155, 92, 74, + 108, 217, 168, 128, 21, 181, 161, 51, 191, 11, 133, 108, 120, 113, 182, 223, 0, 11, 85, 79, 206, 179, 194, 237, 81, 43, + 182, 143, 20, 92, 110, 132, 52, 117, 47, 171, 82, 161, 207, 193, 36, 64, 143, 121, 181, 138, 69, 120, 193, 100, 40, 133, + 87, 137, 247, 162, 73, 227, 132, 203, 45, 159, 174, 45, 103, 253, 150, 251, 146, 108, 25, 142, 7, 115, 153, 253, 200, 21, + 192, 175, 9, 125, 222, 90, 173, 239, 244, 77, 231, 14, 130, 127, 72, 120, 67, 36, 57, 191, 238, 185, 96, 104, 208, 71, + 79, 197, 13, 109, 144, 191, 58, 152, 223, 175, 16, 64, 200, 156, 2, 214, 146, 171, 59, 60, 40, 150, 96, 157, 134, 253, + 115, 183, 116, 206, 7, 64, 100, 124, 238, 234, 163, 16, 189, 18, 249, 133, 168, 235, 159, 89, 253, 212, 38, 206, 165, + 178, 18, 15, 79, 42, 52, 188, 171, 118, 75, 126, 108, 84, 214, 132, 2, 56, 188, 196, 5, 135, 165, 158, 102, 237, 31, 51, + 137, 69, 119, 99, 92, 71, 10, 247, 92, 249, 44, 32, 209, 218, 67, 225, 191, 196, 25, 226, 34, 166, 240, 208, 187, 53, + 140, 94, 56, 249, 203, 5, 10, 234, 254, 144, 72, 20, 241, 172, 26, 164, 156, 202, 158, 160, 202, 131, + ] + .into(), + prv: Some(RsaPrivate { + d: vec![ + 95, 135, 19, 181, 226, 88, 254, 9, 248, 21, 131, 236, 92, 31, 43, 117, 120, 177, 230, 252, 44, 131, 81, 75, 55, 145, + 55, 17, 161, 186, 68, 154, 21, 31, 225, 203, 44, 160, 253, 51, 183, 113, 230, 138, 59, 25, 68, 100, 157, 200, 103, + 173, 28, 30, 82, 64, 187, 133, 62, 95, 36, 179, 52, 89, 177, 64, 40, 210, 214, 99, 107, 239, 236, 30, 141, 169, 116, + 179, 82, 252, 83, 211, 246, 18, 126, 168, 163, 194, 157, 209, 79, 57, 65, 104, 44, 86, 167, 135, 104, 22, 78, 77, + 218, 143, 6, 203, 249, 199, 52, 170, 232, 0, 50, 36, 39, 142, 169, 69, 74, 33, 177, 124, 176, 109, 23, 128, 117, 134, + 140, 192, 91, 61, 182, 255, 29, 253, 195, 213, 99, 120, 180, 237, 173, 237, 240, 195, 122, 76, 220, 38, 209, 212, + 154, 194, 111, 111, 227, 181, 34, 10, 93, 210, 147, 150, 98, 27, 188, 104, 140, 242, 238, 226, 198, 224, 213, 77, + 163, 199, 130, 1, 76, 208, 115, 157, 178, 82, 204, 81, 202, 235, 168, 211, 241, 184, 36, 186, 171, 36, 208, 104, 236, + 144, 50, 100, 215, 214, 120, 171, 8, 240, 110, 201, 231, 226, 61, 150, 6, 40, 183, 68, 191, 148, 179, 105, 70, 86, + 70, 60, 126, 65, 115, 153, 237, 115, 208, 118, 200, 145, 252, 244, 99, 169, 170, 156, 230, 45, 169, 205, 23, 226, 55, + 220, 42, 128, 2, 241, + ] + .into(), + + opt: Some(RsaOptional { + p: vec![ + 243, 120, 190, 236, 139, 204, 25, 122, 12, 92, 43, 36, 191, 189, 211, 42, 191, 58, 223, 177, 98, 59, 182, 118, + 239, 59, 252, 162, 62, 169, 109, 101, 16, 200, 179, 208, 5, 12, 109, 61, 89, 240, 15, 109, 17, 251, 173, 30, 76, + 57, 131, 218, 232, 231, 50, 222, 79, 162, 163, 43, 155, 196, 95, 152, 216, 85, 88, 59, 99, 140, 201, 130, 50, 51, + 169, 73, 120, 156, 20, 120, 251, 92, 235, 149, 33, 132, 50, 169, 85, 165, 88, 72, 122, 116, 221, 250, 25, 86, 88, + 147, 221, 205, 240, 23, 61, 189, 142, 53, 199, 47, 1, 245, 28, 243, 56, 101, 80, 205, 123, 205, 18, 249, 251, 59, + 73, 213, 109, 251, + ] + .into(), + q: vec![ + 221, 215, 206, 71, 215, 46, 98, 175, 180, 75, 233, 164, 20, 188, 224, 34, 216, 12, 17, 241, 115, 7, 106, 183, + 133, 103, 161, 50, 225, 180, 160, 43, 170, 157, 189, 239, 161, 178, 242, 186, 106, 163, 85, 148, 14, 213, 210, + 43, 119, 8, 19, 156, 39, 105, 99, 48, 92, 57, 245, 185, 175, 126, 244, 0, 85, 227, 137, 103, 237, 252, 209, 132, + 138, 139, 232, 158, 44, 225, 42, 154, 61, 85, 84, 187, 241, 60, 197, 131, 25, 8, 118, 183, 156, 69, 236, 236, + 103, 237, 100, 97, 223, 236, 214, 160, 219, 198, 217, 3, 18, 7, 192, 33, 48, 6, 244, 181, 39, 0, 59, 167, 226, + 242, 28, 111, 172, 158, 151, 25, + ] + .into(), + dp: vec![ + 27, 139, 15, 94, 71, 58, 97, 175, 114, 242, 130, 86, 247, 242, 11, 143, 140, 110, 166, 155, 180, 151, 56, 191, + 31, 181, 83, 145, 47, 49, 143, 148, 157, 95, 119, 40, 19, 74, 34, 153, 140, 49, 34, 45, 158, 153, 48, 46, 123, + 69, 14, 107, 151, 105, 128, 81, 178, 4, 158, 28, 242, 212, 54, 84, 94, 52, 217, 116, 110, 128, 160, 211, 63, 198, + 164, 98, 17, 104, 230, 208, 0, 239, 180, 30, 252, 217, 173, 185, 134, 92, 220, 45, 230, 220, 141, 184, 27, 97, + 175, 71, 155, 18, 15, 21, 50, 0, 221, 179, 171, 194, 223, 159, 209, 20, 154, 206, 171, 99, 115, 155, 241, 135, + 162, 42, 68, 226, 6, 61, + ] + .into(), + dq: vec![ + 179, 217, 64, 31, 215, 224, 128, 27, 40, 21, 31, 14, 105, 205, 145, 252, 77, 160, 195, 111, 54, 173, 61, 164, 24, + 224, 33, 188, 137, 101, 17, 49, 53, 121, 250, 192, 234, 27, 148, 82, 243, 31, 5, 195, 41, 159, 201, 106, 121, + 110, 175, 207, 57, 216, 99, 148, 146, 64, 94, 233, 49, 208, 191, 106, 2, 55, 156, 111, 8, 110, 157, 65, 81, 189, + 9, 82, 42, 218, 68, 218, 148, 124, 184, 92, 65, 191, 221, 244, 97, 120, 14, 30, 222, 239, 133, 155, 70, 202, 27, + 70, 137, 238, 141, 54, 13, 215, 16, 154, 63, 164, 206, 235, 88, 239, 90, 181, 254, 47, 95, 45, 197, 124, 56, 247, + 132, 63, 114, 9, + ] + .into(), + qi: vec![ + 27, 35, 63, 167, 162, 107, 95, 36, 162, 207, 91, 104, 22, 2, 155, 89, 95, 137, 116, 141, 227, 67, 140, 169, 187, + 218, 219, 49, 108, 119, 173, 2, 65, 126, 107, 116, 22, 134, 51, 129, 66, 25, 17, 81, 68, 112, 234, 176, 122, 100, + 77, 243, 92, 232, 12, 6, 154, 248, 25, 52, 41, 99, 70, 14, 50, 71, 100, 55, 67, 152, 88, 86, 220, 3, 123, 148, + 143, 169, 187, 25, 63, 152, 118, 70, 39, 93, 107, 199, 36, 124, 59, 158, 87, 45, 39, 183, 72, 249, 145, 124, 172, + 25, 35, 172, 148, 219, 134, 113, 189, 2, 133, 96, 139, 93, 149, 213, 10, 27, 51, 186, 33, 174, 179, 76, 168, 64, + 85, 21, + ] + .into(), + oth: vec![], + }), + }), + }), + prm: Parameters { + alg: Some(Signing::Rs256.into()), + kid: Some("2011-04-29".to_string()), + ..Default::default() + }, + }, + ], + }; + + assert_eq!(jwk, serde_json::from_value(val.clone()).unwrap()); + assert_eq!(val, serde_json::to_value(&jwk).unwrap()); + } + + #[test] + fn b() { + let val = serde_json::json!({ + "kty":"RSA", + "use":"sig", + "kid":"1b94c", + "n":"vrjOfz9Ccdgx5nQudyhdoR17V-IubWMeOZCwX_jj0hgAsz2J_pqYW08PLbK_PdiVGKPrqzmDIsLI7sA25VEnHU1uCLNwBuUiCO11_-7dYbsr4iJmG0Qu2j8DsVyT1azpJC_NG84Ty5KKthuCaPod7iI7w0LK9orSMhBEwwZDCxTWq4aYWAchc8t-emd9qOvWtVMDC2BXksRngh6X5bUYLy6AyHKvj-nUy1wgzjYQDwHMTplCoLtU-o-8SNnZ1tmRoGE9uJkBLdh5gFENabWnU5m1ZqZPdwS-qo-meMvVfJb6jJVWRpl2SUtCnYG2C32qvbWbjZ_jBPD5eunqsIo1vQ", + "e":"AQAB", + "x5c": [ + "MIIDQjCCAiqgAwIBAgIGATz/FuLiMA0GCSqGSIb3DQEBBQUAMGIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYDVQQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1wYmVsbDAeFw0xMzAyMjEyMzI5MTVaFw0xODA4MTQyMjI5MTVaMGIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYDVQQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1wYmVsbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL64zn8/QnHYMeZ0LncoXaEde1fiLm1jHjmQsF/449IYALM9if6amFtPDy2yvz3YlRij66s5gyLCyO7ANuVRJx1NbgizcAblIgjtdf/u3WG7K+IiZhtELto/A7Fck9Ws6SQvzRvOE8uSirYbgmj6He4iO8NCyvaK0jIQRMMGQwsU1quGmFgHIXPLfnpnfajr1rVTAwtgV5LEZ4Iel+W1GC8ugMhyr4/p1MtcIM42EA8BzE6ZQqC7VPqPvEjZ2dbZkaBhPbiZAS3YeYBRDWm1p1OZtWamT3cEvqqPpnjL1XyW+oyVVkaZdklLQp2Btgt9qr21m42f4wTw+Xrp6rCKNb0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAh8zGlfSlcI0o3rYDPBB07aXNswb4ECNIKG0CETTUxmXl9KUL+9gGlqCz5iWLOgWsnrcKcY0vXPG9J1r9AqBNTqNgHq2G03X09266X5CpOe1zFo+Owb1zxtp3PehFdfQJ610CDLEaS9V9Rqp17hCyybEpOGVwe8fnk+fbEL2Bo3UPGrpsHzUoaGpDftmWssZkhpBJKVMJyf/RuP2SmmaIzmnw9JiSlYhzo4tpzd5rFXhjRbg4zW9C+2qok+2+qDM1iJ684gPHMIY8aLWrdgQTxkumGmTqgawR+N5MDtdPTEQ0XfIBc2cJEUyMTY5MPvACWpkA6SdS4xSvdXK3IVfOWA==" + ] + }); + + let jwk = Jwk { + key: Key::Rsa(Rsa { + prv: None, + e: vec![1, 0, 1].into(), + n: vec![ + 190, 184, 206, 127, 63, 66, 113, 216, 49, 230, 116, 46, 119, 40, 93, 161, 29, 123, 87, 226, 46, 109, 99, 30, 57, 144, 176, 95, + 248, 227, 210, 24, 0, 179, 61, 137, 254, 154, 152, 91, 79, 15, 45, 178, 191, 61, 216, 149, 24, 163, 235, 171, 57, 131, 34, 194, + 200, 238, 192, 54, 229, 81, 39, 29, 77, 110, 8, 179, 112, 6, 229, 34, 8, 237, 117, 255, 238, 221, 97, 187, 43, 226, 34, 102, 27, + 68, 46, 218, 63, 3, 177, 92, 147, 213, 172, 233, 36, 47, 205, 27, 206, 19, 203, 146, 138, 182, 27, 130, 104, 250, 29, 238, 34, + 59, 195, 66, 202, 246, 138, 210, 50, 16, 68, 195, 6, 67, 11, 20, 214, 171, 134, 152, 88, 7, 33, 115, 203, 126, 122, 103, 125, + 168, 235, 214, 181, 83, 3, 11, 96, 87, 146, 196, 103, 130, 30, 151, 229, 181, 24, 47, 46, 128, 200, 114, 175, 143, 233, 212, 203, + 92, 32, 206, 54, 16, 15, 1, 204, 78, 153, 66, 160, 187, 84, 250, 143, 188, 72, 217, 217, 214, 217, 145, 160, 97, 61, 184, 153, 1, + 45, 216, 121, 128, 81, 13, 105, 181, 167, 83, 153, 181, 102, 166, 79, 119, 4, 190, 170, 143, 166, 120, 203, 213, 124, 150, 250, + 140, 149, 86, 70, 153, 118, 73, 75, 66, 157, 129, 182, 11, 125, 170, 189, 181, 155, 141, 159, 227, 4, 240, 249, 122, 233, 234, + 176, 138, 53, 189, + ] + .into(), + }), + prm: Parameters { + kid: Some("1b94c".to_string()), + cls: Some(Class::Signing), + x5c: Some(vec![From::from(vec![ + 48, 130, 3, 66, 48, 130, 2, 42, 160, 3, 2, 1, 2, 2, 6, 1, 60, 255, 22, 226, 226, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, + 5, 5, 0, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, 4, 8, 19, 2, 67, 79, 49, 15, 48, 13, 6, + 3, 85, 4, 7, 19, 6, 68, 101, 110, 118, 101, 114, 49, 28, 48, 26, 6, 3, 85, 4, 10, 19, 19, 80, 105, 110, 103, 32, 73, 100, 101, + 110, 116, 105, 116, 121, 32, 67, 111, 114, 112, 46, 49, 23, 48, 21, 6, 3, 85, 4, 3, 19, 14, 66, 114, 105, 97, 110, 32, 67, 97, + 109, 112, 98, 101, 108, 108, 48, 30, 23, 13, 49, 51, 48, 50, 50, 49, 50, 51, 50, 57, 49, 53, 90, 23, 13, 49, 56, 48, 56, 49, 52, + 50, 50, 50, 57, 49, 53, 90, 48, 98, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, 4, 8, 19, 2, 67, 79, + 49, 15, 48, 13, 6, 3, 85, 4, 7, 19, 6, 68, 101, 110, 118, 101, 114, 49, 28, 48, 26, 6, 3, 85, 4, 10, 19, 19, 80, 105, 110, 103, + 32, 73, 100, 101, 110, 116, 105, 116, 121, 32, 67, 111, 114, 112, 46, 49, 23, 48, 21, 6, 3, 85, 4, 3, 19, 14, 66, 114, 105, 97, + 110, 32, 67, 97, 109, 112, 98, 101, 108, 108, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, + 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 190, 184, 206, 127, 63, 66, 113, 216, 49, 230, 116, 46, 119, 40, 93, 161, 29, 123, 87, + 226, 46, 109, 99, 30, 57, 144, 176, 95, 248, 227, 210, 24, 0, 179, 61, 137, 254, 154, 152, 91, 79, 15, 45, 178, 191, 61, 216, + 149, 24, 163, 235, 171, 57, 131, 34, 194, 200, 238, 192, 54, 229, 81, 39, 29, 77, 110, 8, 179, 112, 6, 229, 34, 8, 237, 117, 255, + 238, 221, 97, 187, 43, 226, 34, 102, 27, 68, 46, 218, 63, 3, 177, 92, 147, 213, 172, 233, 36, 47, 205, 27, 206, 19, 203, 146, + 138, 182, 27, 130, 104, 250, 29, 238, 34, 59, 195, 66, 202, 246, 138, 210, 50, 16, 68, 195, 6, 67, 11, 20, 214, 171, 134, 152, + 88, 7, 33, 115, 203, 126, 122, 103, 125, 168, 235, 214, 181, 83, 3, 11, 96, 87, 146, 196, 103, 130, 30, 151, 229, 181, 24, 47, + 46, 128, 200, 114, 175, 143, 233, 212, 203, 92, 32, 206, 54, 16, 15, 1, 204, 78, 153, 66, 160, 187, 84, 250, 143, 188, 72, 217, + 217, 214, 217, 145, 160, 97, 61, 184, 153, 1, 45, 216, 121, 128, 81, 13, 105, 181, 167, 83, 153, 181, 102, 166, 79, 119, 4, 190, + 170, 143, 166, 120, 203, 213, 124, 150, 250, 140, 149, 86, 70, 153, 118, 73, 75, 66, 157, 129, 182, 11, 125, 170, 189, 181, 155, + 141, 159, 227, 4, 240, 249, 122, 233, 234, 176, 138, 53, 189, 2, 3, 1, 0, 1, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 5, 5, + 0, 3, 130, 1, 1, 0, 135, 204, 198, 149, 244, 165, 112, 141, 40, 222, 182, 3, 60, 16, 116, 237, 165, 205, 179, 6, 248, 16, 35, 72, + 40, 109, 2, 17, 52, 212, 198, 101, 229, 244, 165, 11, 251, 216, 6, 150, 160, 179, 230, 37, 139, 58, 5, 172, 158, 183, 10, 113, + 141, 47, 92, 241, 189, 39, 90, 253, 2, 160, 77, 78, 163, 96, 30, 173, 134, 211, 117, 244, 247, 110, 186, 95, 144, 169, 57, 237, + 115, 22, 143, 142, 193, 189, 115, 198, 218, 119, 61, 232, 69, 117, 244, 9, 235, 93, 2, 12, 177, 26, 75, 213, 125, 70, 170, 117, + 238, 16, 178, 201, 177, 41, 56, 101, 112, 123, 199, 231, 147, 231, 219, 16, 189, 129, 163, 117, 15, 26, 186, 108, 31, 53, 40, + 104, 106, 67, 126, 217, 150, 178, 198, 100, 134, 144, 73, 41, 83, 9, 201, 255, 209, 184, 253, 146, 154, 102, 136, 206, 105, 240, + 244, 152, 146, 149, 136, 115, 163, 139, 105, 205, 222, 107, 21, 120, 99, 69, 184, 56, 205, 111, 66, 251, 106, 168, 147, 237, 190, + 168, 51, 53, 136, 158, 188, 226, 3, 199, 48, 134, 60, 104, 181, 171, 118, 4, 19, 198, 75, 166, 26, 100, 234, 129, 172, 17, 248, + 222, 76, 14, 215, 79, 76, 68, 52, 93, 242, 1, 115, 103, 9, 17, 76, 140, 77, 142, 76, 62, 240, 2, 90, 153, 0, 233, 39, 82, 227, + 20, 175, 117, 114, 183, 33, 87, 206, 88, + ])]), + ..Default::default() + }, + }; + + assert_eq!(jwk, serde_json::from_value(val.clone()).unwrap()); + assert_eq!(val, serde_json::to_value(&jwk).unwrap()); + } +} + +#[cfg(test)] +mod rfc8037 { + use crate::jwk::Key; + use crate::jwk::{okp::*, prm::*, Jwk}; + #[test] + fn a1() { + let val = serde_json::json!({ + "kty":"OKP", + "crv":"Ed25519", + "d":"nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A", + "x":"11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo" + }); + + let jwk = Jwk { + key: Key::Okp(Okp { + crv: OkpCurves::Ed25519, + d: Some( + vec![ + 157, 97, 177, 157, 239, 253, 90, 96, 186, 132, 74, 244, 146, 236, 44, 196, 68, 73, 197, 105, 123, 50, 105, 25, 112, 59, 172, + 3, 28, 174, 127, 96, + ] + .into(), + ), + x: vec![ + 215, 90, 152, 1, 130, 177, 10, 183, 213, 75, 254, 211, 201, 100, 7, 58, 14, 225, 114, 243, 218, 166, 35, 37, 175, 2, 26, 104, + 247, 7, 81, 26, + ] + .into(), + }), + prm: Parameters::default(), + }; + + assert_eq!(jwk, serde_json::from_value(val.clone()).unwrap()); + assert_eq!(val, serde_json::to_value(jwk).unwrap()); + } + + #[test] + fn a2() { + let val = serde_json::json!({ + "kty":"OKP", + "crv":"Ed25519", + "x":"11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo" + }); + + let jwk = Jwk { + key: Key::Okp(Okp { + crv: OkpCurves::Ed25519, + d: None, + x: vec![ + 215, 90, 152, 1, 130, 177, 10, 183, 213, 75, 254, 211, 201, 100, 7, 58, 14, 225, 114, 243, 218, 166, 35, 37, 175, 2, 26, 104, + 247, 7, 81, 26, + ] + .into(), + }), + prm: Parameters::default(), + }; + + assert_eq!(jwk, serde_json::from_value(val.clone()).unwrap()); + assert_eq!(val, serde_json::to_value(jwk).unwrap()); + } + + #[test] + fn a6() { + let val = serde_json::json!({ + "kty":"OKP", + "crv":"X25519", + "kid":"Bob", + "x":"3p7bfXt9wbTTW2HC7OQ1Nz-DQ8hbeGdNrfx-FG-IK08" + }); + + let jwk = Jwk { + key: Key::Okp(Okp { + crv: OkpCurves::X25519, + d: None, + x: vec![ + 222, 158, 219, 125, 123, 125, 193, 180, 211, 91, 97, 194, 236, 228, 53, 55, 63, 131, 67, 200, 91, 120, 103, 77, 173, 252, 126, + 20, 111, 136, 43, 79, + ] + .into(), + }), + prm: Parameters { + kid: Some("Bob".to_string()), + ..Default::default() + }, + }; + + assert_eq!(jwk, serde_json::from_value(val.clone()).unwrap()); + assert_eq!(val, serde_json::to_value(jwk).unwrap()); + } + + #[test] + fn a7() { + let val = serde_json::json!({ + "kty": "OKP", + "crv": "X448", + "kid": "Dave", + "x": "PreoKbDNIPW8_AtZm2_sz22kYnEHvbDU80W0MCfYuXL8PjT7QjKhPKcG3LV67D2uB73BxnvzNgk" + }); + + let jwk = Jwk { + key: Key::Okp(Okp { + crv: OkpCurves::X448, + d: None, + x: vec![ + 62, 183, 168, 41, 176, 205, 32, 245, 188, 252, 11, 89, 155, 111, 236, 207, 109, 164, 98, 113, 7, 189, 176, 212, 243, 69, 180, 48, + 39, 216, 185, 114, 252, 62, 52, 251, 66, 50, 161, 60, 167, 6, 220, 181, 122, 236, 61, 174, 7, 189, 193, 198, 123, 243, 54, 9, + ] + .into(), + }), + prm: Parameters { + kid: Some("Dave".to_string()), + ..Default::default() + }, + }; + + assert_eq!(jwk, serde_json::from_value(val.clone()).unwrap()); + assert_eq!(val, serde_json::to_value(jwk).unwrap()); + } +} diff --git a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/Cargo.toml b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/Cargo.toml index f90113a3..b85efe24 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/Cargo.toml @@ -14,6 +14,7 @@ message-api.workspace = true mongodb.workspace = true multibase.workspace = true serde.workspace = true +paste.workspace = true async-trait.workspace = true serde_json.workspace = true thiserror.workspace = true @@ -38,3 +39,4 @@ shared = { workspace = true, features = ["test-utils"] } [features] default = ["stateful"] stateful = [] +stateless = [] diff --git a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/midlw.rs b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/midlw.rs index c5efadd6..a106c159 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/midlw.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/midlw.rs @@ -33,10 +33,10 @@ mod tests { use super::*; use shared::utils::tests_utils::tests::*; - #[cfg(feature = "stateless")] - use crate::model::stateless::coord::{ - MediationRequest as StatelessMediationRequest, MediatorService, - }; + // #[cfg(feature = "stateless")] + // use crate::model::stateless::coord::{ + // MediationRequest as StatelessMediationRequest, MediatorService, + // }; use didcomm::Message; @@ -93,104 +93,104 @@ mod tests { ); } - #[cfg(feature = "stateless")] - #[tokio::test] - async fn test_parse_message_body_into_stateless_mediation_request() { - let (_, state) = setup(); - - /* Positive cases */ - - let mediation_request = StatelessMediationRequest { - id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), - message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), - did: _edge_did(), - services: [MediatorService::Inbox, MediatorService::Outbox] - .into_iter() - .collect(), - ..Default::default() - }; - - let msg = Message::build( - "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), - MEDIATE_REQUEST_DIC_1_0.to_string(), - json!(&mediation_request), - ) - .to(_mediator_did(&state)) - .from(_edge_did()) - .finalize(); - - let parsed_mediation_request = parse_message_body_into_mediation_request(&msg).unwrap(); - #[allow(irrefutable_let_patterns)] - let MediationRequest::Stateless(parsed_mediation_request) = parsed_mediation_request - else { - panic!() - }; - assert_eq!(json!(mediation_request), json!(parsed_mediation_request)); - - /* Negative cases */ - - let msg = Message::build( - "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), - "invalid-type".to_string(), - json!("not-mediation-request"), - ) - .to(_mediator_did(&state)) - .from(_edge_did()) - .finalize(); - - assert_error( - parse_message_body_into_mediation_request(&msg).unwrap_err(), - StatusCode::BAD_REQUEST, - &MediationError::UnexpectedMessageFormat.json().0, - ) - .await; - } - - #[cfg(feature = "stateless")] - #[tokio::test] - async fn test_ensure_mediation_request_type() { - /* Positive cases */ - - let mediation_request = StatelessMediationRequest { - id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), - message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), - did: _edge_did(), - services: [MediatorService::Inbox, MediatorService::Outbox] - .into_iter() - .collect(), - ..Default::default() - }; - - assert!( - ensure_mediation_request_type(&json!(mediation_request), MEDIATE_REQUEST_DIC_1_0) - .is_ok() - ); - assert_error( - ensure_mediation_request_type(&json!(mediation_request), MEDIATE_REQUEST_2_0) - .unwrap_err(), - StatusCode::BAD_REQUEST, - &MediationError::InvalidMessageType.json().0, - ) - .await; - - /* Negative cases */ - - let mediation_request = StatelessMediationRequest { - id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), - message_type: "invalid-type".to_string(), - did: _edge_did(), - services: [MediatorService::Inbox, MediatorService::Outbox] - .into_iter() - .collect(), - ..Default::default() - }; - - assert_error( - ensure_mediation_request_type(&json!(mediation_request), MEDIATE_REQUEST_DIC_1_0) - .unwrap_err(), - StatusCode::BAD_REQUEST, - &MediationError::InvalidMessageType.json().0, - ) - .await; - } + // #[cfg(feature = "stateless")] + // #[tokio::test] + // async fn test_parse_message_body_into_stateless_mediation_request() { + // let state = setup(); + + // /* Positive cases */ + + // let mediation_request = StatelessMediationRequest { + // id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), + // message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), + // did: _edge_did(), + // services: [MediatorService::Inbox, MediatorService::Outbox] + // .into_iter() + // .collect(), + // ..Default::default() + // }; + + // let msg = Message::build( + // "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), + // MEDIATE_REQUEST_DIC_1_0.to_string(), + // json!(&mediation_request), + // ) + // .to(_mediator_did(&state)) + // .from(_edge_did()) + // .finalize(); + + // let parsed_mediation_request = parse_message_body_into_mediation_request(&msg).unwrap(); + // #[allow(irrefutable_let_patterns)] + // let MediationRequest::Stateless(parsed_mediation_request) = parsed_mediation_request + // else { + // panic!() + // }; + // assert_eq!(json!(mediation_request), json!(parsed_mediation_request)); + + // /* Negative cases */ + + // let msg = Message::build( + // "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), + // "invalid-type".to_string(), + // json!("not-mediation-request"), + // ) + // .to(_mediator_did(&state)) + // .from(_edge_did()) + // .finalize(); + + // assert_error( + // parse_message_body_into_mediation_request(&msg).unwrap_err(), + // StatusCode::BAD_REQUEST, + // &MediationError::UnexpectedMessageFormat.json().0, + // ) + // .await; + // } + + // // #[cfg(feature = "stateless")] + // #[tokio::test] + // async fn test_ensure_mediation_request_type() { + // /* Positive cases */ + + // let mediation_request = StatelessMediationRequest { + // id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), + // message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), + // did: _edge_did(), + // services: [MediatorService::Inbox, MediatorService::Outbox] + // .into_iter() + // .collect(), + // ..Default::default() + // }; + + // assert!( + // ensure_mediation_request_type(&json!(mediation_request), MEDIATE_REQUEST_DIC_1_0) + // .is_ok() + // ); + // assert_error( + // ensure_mediation_request_type(&json!(mediation_request), MEDIATE_REQUEST_2_0) + // .unwrap_err(), + // StatusCode::BAD_REQUEST, + // &MediationError::InvalidMessageType.json().0, + // ) + // .await; + + // /* Negative cases */ + + // let mediation_request = StatelessMediationRequest { + // id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), + // message_type: "invalid-type".to_string(), + // did: _edge_did(), + // services: [MediatorService::Inbox, MediatorService::Outbox] + // .into_iter() + // .collect(), + // ..Default::default() + // }; + + // assert_error( + // ensure_mediation_request_type(&json!(mediation_request), MEDIATE_REQUEST_DIC_1_0) + // .unwrap_err(), + // StatusCode::BAD_REQUEST, + // &MediationError::InvalidMessageType.json().0, + // ) + // .await; + // } } diff --git a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/mod.rs b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/mod.rs index a56ed3c3..bc4772ff 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/mod.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/mod.rs @@ -1,7 +1,7 @@ mod midlw; #[cfg(feature = "stateful")] -pub mod stateful; +pub(crate) mod stateful; #[allow(unexpected_cfgs)] #[cfg(feature = "stateless")] -mod stateless; +pub(crate) mod stateless; diff --git a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/stateless.rs b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/stateless.rs index 61862795..b5973860 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/stateless.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/stateless.rs @@ -1,65 +1,107 @@ -use axum::response::Response; -use didcomm::Message; -use serde_json::json; -use uuid::Uuid; +use std::sync::Arc; -use super::midlw::{self}; -use shared::{ - constant::{MEDIATE_DENY_DIC_1_0, MEDIATE_GRANT_DIC_1_0, MEDIATE_REQUEST_DIC_1_0}, +use super::midlw::{ensure_jwm_type_is_mediation_request, ensure_mediation_request_type}; +use crate::{ + constants::{MEDIATE_DENY_DIC_1_0, MEDIATE_GRANT_DIC_1_0, MEDIATE_REQUEST_DIC_1_0}, + errors::MediationError, model::stateless::{ coord::{MediationDeny, MediationGrant, MediationRequest, MediatorService}, dic::{CompactDIC, DICPayload, JwtAssertable}, }, - web::AppState, }; +use did_utils::didcore::VerificationMethodType; +use didcomm::Message; +use mongodb::bson::doc; +use serde_json::json; +use shared::{ + midlw::ensure_transport_return_route_is_decorated_all, + state::{AppState, AppStateRepository}, +}; +use uuid::Uuid; /// Process a DIC-wise mediation request -pub async fn process_plain_mediation_request_over_dics( - state: &AppState, - plain_message: &Message, - mediation_request: &MediationRequest, -) -> Result { +pub(crate) async fn process_plain_mediation_request_over_dics( + state: Arc, + message: Message, +) -> Result, MediationError> { + // Convert to MediationRequest + let mediation_request: MediationRequest = + serde_json::from_value(json!(message)).map_err(|err| { + tracing::error!("Failed to deserialize MediationRequest: {err:?}"); + MediationError::UnexpectedMessageFormat + })?; + // Set convenient aliases let requester_did = &mediation_request.did; let mediator_did = &state.diddoc.id; + let AppStateRepository { keystore, .. } = state.repository.as_ref().ok_or_else(|| { + tracing::error!("Missing persistence layer"); + MediationError::InternalServerError + })?; + // Check message type compliance - midlw::ensure_mediation_request_type(&json!(mediation_request), MEDIATE_REQUEST_DIC_1_0)?; + ensure_mediation_request_type(&json!(mediation_request), MEDIATE_REQUEST_DIC_1_0)?; // Check message type compliance - midlw::run!(ensure_jwm_type_is_mediation_request(&plain_message)); + ensure_jwm_type_is_mediation_request(&message)?; - // Check explicit agreement to HTTP responding - midlw::run!(ensure_transport_return_route_is_decorated_all( - &plain_message - )); + // This is to Check explicit agreement to HTTP responding + ensure_transport_return_route_is_decorated_all(&message) + .map_err(|_| MediationError::NoReturnRouteAllDecoration)?; /* Deny mediate request if sender is not requester */ - let sender_did = plain_message - .from - .as_ref() - .expect("should not panic as anonymous requests are rejected earlier"); + let sender_did = message.from.as_ref().unwrap(); if sender_did != requester_did { - return Ok(Message::build( - format!("urn:uuid:{}", Uuid::new_v4()), - MEDIATE_DENY_DIC_1_0.to_string(), - json!(MediationDeny { - id: format!("urn:uuid:{}", Uuid::new_v4()), - message_type: MEDIATE_DENY_DIC_1_0.to_string(), - ..Default::default() - }), - ) - .to(sender_did.clone()) - .from(mediator_did.clone()) - .finalize()); + return Ok(Some( + Message::build( + format!("urn:uuid:{}", Uuid::new_v4()), + MEDIATE_DENY_DIC_1_0.to_string(), + json!(MediationDeny { + id: format!("urn:uuid:{}", Uuid::new_v4()), + message_type: MEDIATE_DENY_DIC_1_0.to_string(), + ..Default::default() + }), + ) + .to(sender_did.clone()) + .from(mediator_did.clone()) + .finalize(), + )); } /* Issue mediate grant response */ - // Expand assertion key - let (kid, jwk) = &state.assertion_jwk; + // Extract assertion key id + let kid = state + .diddoc + .assertion_method + .as_ref() + .and_then(|vms| vms.first()) + .map(|vm| match vm { + VerificationMethodType::Embedded(key) => &key.id, + VerificationMethodType::Reference(id) => id, + }) + .cloned() + .ok_or_else(|| { + tracing::error!("No assertion key found in DID document"); + MediationError::InternalServerError + })?; + + // Extract assertion key + let jwk = keystore + .find_one_by(doc! { "kid": kid.clone() }) + .await + .map_err(|err| { + tracing::error!("Error fetching secret: {err:?}"); + MediationError::InternalServerError + })? + .ok_or_else(|| { + tracing::error!("Secret not found"); + MediationError::InternalServerError + })? + .secret_material; // Issue verifiable credentials for DICs let vdic: Vec<_> = mediation_request @@ -74,7 +116,7 @@ pub async fn process_plain_mediation_request_over_dics( }; let jws = dic - .sign(jwk, Some(kid.clone())) + .sign(&jwk, Some(kid.clone())) .expect("could not sign DIC payload"); match service { @@ -92,548 +134,360 @@ pub async fn process_plain_mediation_request_over_dics( ..Default::default() }; - Ok(Message::build( - format!("urn:uuid:{}", Uuid::new_v4()), - mediation_grant.message_type.clone(), - json!(mediation_grant), - ) - .to(requester_did.clone()) - .from(mediator_did.clone()) - .finalize()) -} - -#[cfg(test)] -mod tests { - use super::*; - - use axum::{ - body::Body, - http::{header::CONTENT_TYPE, Method, Request}, - }; - use hyper::StatusCode; - use serde_json::Value; - use tower::util::ServiceExt; - - use crate::{ - constant::DIDCOMM_ENCRYPTED_MIME_TYPE, - jose::jws, - web::{error::MediationError, handler::tests::*}, - }; - - #[tokio::test] - async fn test_comprehensive_mediation_grant_response() { - let (app, state) = setup(); - - // Build message - let msg = Message::build( - "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), - MEDIATE_REQUEST_DIC_1_0.to_string(), - json!(MediationRequest { - id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), - message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), - did: _edge_did(), - services: [MediatorService::Inbox, MediatorService::Outbox] - .into_iter() - .collect(), - ..Default::default() - }), - ) - .header( - "~transport".into(), - json!({ - "return_route": "all" - }), - ) - .to(_mediator_did(&state)) - .from(_edge_did()) - .finalize(); - - // Encrypt message for mediator - let packed_msg = _edge_pack_message(&state, &msg, Some(_edge_did()), _mediator_did(&state)) - .await - .unwrap(); - - // Send request - let response = app - .oneshot( - Request::builder() - .uri(String::from("/")) - .method(Method::POST) - .header(CONTENT_TYPE, DIDCOMM_ENCRYPTED_MIME_TYPE) - .body(Body::from(packed_msg)) - .unwrap(), - ) - .await - .unwrap(); - - // Assert response's metadata - assert_eq!(response.status(), StatusCode::ACCEPTED); - assert_eq!( - response.headers().get(CONTENT_TYPE).unwrap(), - DIDCOMM_ENCRYPTED_MIME_TYPE - ); - - // Parse response's body - let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); - let body: Value = serde_json::from_slice(&body).unwrap(); - let response = serde_json::to_string(&body).unwrap(); - - // Decrypt response - let msg: Message = _edge_unpack_message(&state, &response).await.unwrap(); - - // Assert metadata - assert_eq!(msg.type_, MEDIATE_GRANT_DIC_1_0); - assert_eq!(msg.from.unwrap(), _mediator_did(&state)); - assert_eq!(msg.to.unwrap(), [_edge_did()]); - - // Parse alleged mediation grant response - let mediation_grant: MediationGrant = serde_json::from_value(msg.body).unwrap(); - - // Assert mediation grant's properties - assert!(mediation_grant.id.starts_with("urn:uuid:")); - assert_eq!(mediation_grant.message_type, MEDIATE_GRANT_DIC_1_0); - assert_eq!(mediation_grant.endpoint, state.public_domain); - - // Assert that mediation grant embeds DICs for requested services - assert_eq!( - _inspect_dic_tags(&mediation_grant.dic), - vec!["inbox", "outbox"] - ); - - // Verify issued DICs - assert!({ - let mut iter = mediation_grant.dic.iter(); - iter.all(|dic| { - jws::verify_compact_jws(&dic.plain_jws(), &state.assertion_jwk.1).is_ok() - }) - }); - } - - #[tokio::test] - async fn test_mediation_grant_response_with_single_channel() { - let (app, state) = setup(); - - for service in &[MediatorService::Inbox, MediatorService::Outbox] { - let msg = Message::build( - "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), - MEDIATE_REQUEST_DIC_1_0.to_string(), - json!(MediationRequest { - id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), - message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), - did: _edge_did(), - services: [service.clone()].into_iter().collect(), - ..Default::default() - }), - ) - .header( - "~transport".into(), - json!({ - "return_route": "all" - }), - ) - .to(_mediator_did(&state)) - .from(_edge_did()) - .finalize(); - - let packed_msg = - _edge_pack_message(&state, &msg, Some(_edge_did()), _mediator_did(&state)) - .await - .unwrap(); - - // Send request - let response = app - .clone() - .oneshot( - Request::builder() - .uri(String::from("/")) - .method(Method::POST) - .header(CONTENT_TYPE, DIDCOMM_ENCRYPTED_MIME_TYPE) - .body(Body::from(packed_msg)) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::ACCEPTED); - assert_eq!( - response.headers().get(CONTENT_TYPE).unwrap(), - DIDCOMM_ENCRYPTED_MIME_TYPE - ); - - let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); - let body: Value = serde_json::from_slice(&body).unwrap(); - let response = serde_json::to_string(&body).unwrap(); - - let msg: Message = _edge_unpack_message(&state, &response).await.unwrap(); - let mediation_grant: MediationGrant = serde_json::from_value(msg.body).unwrap(); - - assert_eq!( - _inspect_dic_tags(&mediation_grant.dic), - vec![match service { - MediatorService::Inbox => "inbox", - MediatorService::Outbox => "outbox", - }] - ); - } - } - - #[tokio::test] - async fn test_mediation_deny_response_for_sender_requester_unmatch() { - let (app, state) = setup(); - - let msg = Message::build( - "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), - MEDIATE_REQUEST_DIC_1_0.to_string(), - json!(MediationRequest { - id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), - message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), - did: "did:key:unknown".to_string(), - services: [MediatorService::Inbox, MediatorService::Outbox] - .into_iter() - .collect(), - ..Default::default() - }), - ) - .header( - "~transport".into(), - json!({ - "return_route": "all" - }), - ) - .to(_mediator_did(&state)) - .from(_edge_did()) - .finalize(); - - let packed_msg = _edge_pack_message(&state, &msg, Some(_edge_did()), _mediator_did(&state)) - .await - .unwrap(); - - // Send request - let response = app - .oneshot( - Request::builder() - .uri(String::from("/")) - .method(Method::POST) - .header(CONTENT_TYPE, DIDCOMM_ENCRYPTED_MIME_TYPE) - .body(Body::from(packed_msg)) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::ACCEPTED); - assert_eq!( - response.headers().get(CONTENT_TYPE).unwrap(), - DIDCOMM_ENCRYPTED_MIME_TYPE - ); - - let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); - let body: Value = serde_json::from_slice(&body).unwrap(); - let response = serde_json::to_string(&body).unwrap(); - - let msg: Message = _edge_unpack_message(&state, &response).await.unwrap(); - assert_eq!(msg.type_, MEDIATE_DENY_DIC_1_0); - assert_eq!(msg.from.unwrap(), _mediator_did(&state)); - assert_eq!(msg.to.unwrap(), [_edge_did()]); - - let mediation_deny: MediationDeny = serde_json::from_value(msg.body).unwrap(); - assert_eq!(mediation_deny.message_type, MEDIATE_DENY_DIC_1_0); - } - - #[tokio::test] - async fn test_bad_request_on_invalid_payload_content_type() { - let (app, state) = setup(); - - let msg = Message::build( - "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), - MEDIATE_REQUEST_DIC_1_0.to_string(), - json!(MediationRequest { - id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), - message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), - did: _edge_did(), - services: [MediatorService::Inbox, MediatorService::Outbox] - .into_iter() - .collect(), - ..Default::default() - }), - ) - .header( - "~transport".into(), - json!({ - "return_route": "all" - }), - ) - .to(_mediator_did(&state)) - .from(_edge_did()) - .finalize(); - - let packed_msg = _edge_pack_message(&state, &msg, Some(_edge_did()), _mediator_did(&state)) - .await - .unwrap(); - - // Send request - let response = app - .oneshot( - Request::builder() - .uri(String::from("/")) - .method(Method::POST) - .body(Body::from(packed_msg)) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.headers().get(CONTENT_TYPE).unwrap(), - "application/json" - ); - - let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); - let body: Value = serde_json::from_slice(&body).unwrap(); - - assert_eq!( - json_canon::to_string(&body).unwrap(), - json_canon::to_string(&MediationError::NotDidcommEncryptedPayload.json().0).unwrap() - ) - } - - #[tokio::test] - async fn test_bad_request_on_unpacking_failure() { - let (app, state) = setup(); - - let msg = Message::build( - "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), - MEDIATE_REQUEST_DIC_1_0.to_string(), - json!(MediationRequest { - id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), - message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), - did: _edge_did(), - services: [MediatorService::Inbox, MediatorService::Outbox] - .into_iter() - .collect(), - ..Default::default() - }), - ) - .header( - "~transport".into(), - json!({ - "return_route": "all" - }), - ) - .to(_edge_did()) - .from(_edge_did()) - .finalize(); - - // Pack for edge instead of mediator - let packed_msg = _edge_pack_message(&state, &msg, Some(_edge_did()), _edge_did()) - .await - .unwrap(); - - // Send request - let response = app - .oneshot( - Request::builder() - .uri(String::from("/")) - .method(Method::POST) - .header(CONTENT_TYPE, DIDCOMM_ENCRYPTED_MIME_TYPE) - .body(Body::from(packed_msg)) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.headers().get(CONTENT_TYPE).unwrap(), - "application/json" - ); - - let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); - let body: Value = serde_json::from_slice(&body).unwrap(); - - assert_eq!( - json_canon::to_string(&body).unwrap(), - json_canon::to_string(&MediationError::MessageUnpackingFailure.json().0).unwrap() - ) - } - - #[tokio::test] - async fn test_bad_request_on_invalid_jwm_header_message_type() { - let (app, state) = setup(); - - let msg = Message::build( - "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), - "invalid-message-type".to_string(), - json!(MediationRequest { - id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), - message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), - did: _edge_did(), - services: [MediatorService::Inbox, MediatorService::Outbox] - .into_iter() - .collect(), - ..Default::default() - }), - ) - .header( - "~transport".into(), - json!({ - "return_route": "all" - }), - ) - .to(_mediator_did(&state)) - .from(_edge_did()) - .finalize(); - - let packed_msg = _edge_pack_message(&state, &msg, Some(_edge_did()), _mediator_did(&state)) - .await - .unwrap(); - - // Send request - let response = app - .oneshot( - Request::builder() - .uri(String::from("/")) - .method(Method::POST) - .header(CONTENT_TYPE, DIDCOMM_ENCRYPTED_MIME_TYPE) - .body(Body::from(packed_msg)) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.headers().get(CONTENT_TYPE).unwrap(), - "application/json" - ); - - let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); - let body: Value = serde_json::from_slice(&body).unwrap(); - - assert_eq!( - json_canon::to_string(&body).unwrap(), - json_canon::to_string(&MediationError::InvalidMessageType.json().0).unwrap() - ) - } - - #[tokio::test] - async fn test_bad_request_on_missing_return_route_decoration() { - let (app, state) = setup(); - - let msg = Message::build( - "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), - MEDIATE_REQUEST_DIC_1_0.to_string(), - json!(MediationRequest { - id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), - message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), - did: _edge_did(), - services: [MediatorService::Inbox, MediatorService::Outbox] - .into_iter() - .collect(), - ..Default::default() - }), - ) - .to(_mediator_did(&state)) - .from(_edge_did()) - .finalize(); - - let packed_msg = _edge_pack_message(&state, &msg, Some(_edge_did()), _mediator_did(&state)) - .await - .unwrap(); - // Send request - let response = app - .oneshot( - Request::builder() - .uri(String::from("/")) - .method(Method::POST) - .header(CONTENT_TYPE, DIDCOMM_ENCRYPTED_MIME_TYPE) - .body(Body::from(packed_msg)) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.headers().get(CONTENT_TYPE).unwrap(), - "application/json" - ); - - let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); - let body: Value = serde_json::from_slice(&body).unwrap(); - - assert_eq!( - json_canon::to_string(&body).unwrap(), - json_canon::to_string(&MediationError::NoReturnRouteAllDecoration.json().0).unwrap() - ) - } - - #[tokio::test] - async fn test_bad_request_on_non_mediate_request_payload() { - let (app, state) = setup(); - - let msg = Message::build( - "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), - MEDIATE_REQUEST_DIC_1_0.to_string(), - json!("not-mediate-request"), - ) - .header( - "~transport".into(), - json!({ - "return_route": "all" - }), - ) - .to(_mediator_did(&state)) - .from(_edge_did()) - .finalize(); - - let packed_msg = _edge_pack_message(&state, &msg, Some(_edge_did()), _mediator_did(&state)) - .await - .unwrap(); - - // Send request - let response = app - .oneshot( - Request::builder() - .uri(String::from("/")) - .method(Method::POST) - .header(CONTENT_TYPE, DIDCOMM_ENCRYPTED_MIME_TYPE) - .body(Body::from(packed_msg)) - .unwrap(), - ) - .await - .unwrap(); - - assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.headers().get(CONTENT_TYPE).unwrap(), - "application/json" - ); - - let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); - let body: Value = serde_json::from_slice(&body).unwrap(); - - assert_eq!( - json_canon::to_string(&body).unwrap(), - json_canon::to_string(&MediationError::UnexpectedMessageFormat.json().0).unwrap() + Ok(Some( + Message::build( + format!("urn:uuid:{}", Uuid::new_v4()), + mediation_grant.message_type.clone(), + json!(mediation_grant), ) - } - - //------------------------------------------------------------------------ - // Helpers --------------------------------------------------------------- - //------------------------------------------------------------------------ - - fn _inspect_dic_tags(vdic: &[CompactDIC]) -> Vec<&'static str> { - let mut tags: Vec<_> = vdic - .iter() - .map(|dic| match dic { - CompactDIC::Inbox(_) => "inbox", - CompactDIC::Outbox(_) => "outbox", - }) - .collect(); - - tags.sort(); - tags - } + .to(requester_did.clone()) + .from(mediator_did.clone()) + .finalize(), + )) } + +// #[cfg(test)] +// mod tests { +// use super::*; + +// use shared::utils::tests_utils::tests::*; + +// use crate::errors::MediationError; + +// #[tokio::test] +// async fn test_comprehensive_mediation_grant_response() { +// let state = setup(); + +// // Build message +// let msg = Message::build( +// "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), +// MEDIATE_REQUEST_DIC_1_0.to_string(), +// json!(MediationRequest { +// id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), +// message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), +// did: _edge_did(), +// services: [MediatorService::Inbox, MediatorService::Outbox] +// .into_iter() +// .collect(), +// ..Default::default() +// }), +// ) +// .header("return-route".to_owned(), json!("all")) +// .to(_mediator_did(&state)) +// .from(_edge_did()) +// .finalize(); + +// // Process request +// let response = process_plain_mediation_request_over_dics(Arc::clone(&state), msg) +// .await +// .unwrap() +// .expect("Response should not be None"); + +// // Assert metadata +// assert_eq!(response.clone().type_, MEDIATE_GRANT_DIC_1_0); +// assert_eq!(response.clone().from.unwrap(), _mediator_did(&state)); +// assert_eq!(response.clone().to.unwrap(), [_edge_did()]); + +// // Parse alleged mediation grant response +// let mediation_grant: MediationGrant = serde_json::from_value(json!(response)).unwrap(); + +// // Assert mediation grant's properties +// assert!(mediation_grant.id.starts_with("urn:uuid:")); +// assert_eq!(mediation_grant.message_type, MEDIATE_GRANT_DIC_1_0); +// assert_eq!(mediation_grant.endpoint, state.public_domain); + +// // Assert that mediation grant embeds DICs for requested services +// assert_eq!( +// _inspect_dic_tags(&mediation_grant.dic), +// vec!["inbox", "outbox"] +// ); + +// // Verify issued DICs +// // assert!({ +// // let mut iter = mediation_grant.dic.iter(); +// // iter.all(|dic| { +// // jws::verify_compact_jws(&dic.plain_jws(), &state.assertion_jwk.1).is_ok() +// // }) +// // }); +// } + +// #[tokio::test] +// async fn test_mediation_grant_response_with_single_channel() { +// let state = setup(); + +// for service in &[MediatorService::Inbox, MediatorService::Outbox] { +// let msg = Message::build( +// "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), +// MEDIATE_REQUEST_DIC_1_0.to_string(), +// json!(MediationRequest { +// id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), +// message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), +// did: _edge_did(), +// services: [service.clone()].into_iter().collect(), +// ..Default::default() +// }), +// ) +// .header("return-route".to_owned(), json!("all")) +// .to(_mediator_did(&state)) +// .from(_edge_did()) +// .finalize(); + +// let response = process_plain_mediation_request_over_dics(Arc::clone(&state), msg) +// .await +// .unwrap() +// .expect("Response should not be None"); + +// let mediation_grant: MediationGrant = serde_json::from_value(json!(response)).unwrap(); + +// assert_eq!( +// _inspect_dic_tags(&mediation_grant.dic), +// vec![match service { +// MediatorService::Inbox => "inbox", +// MediatorService::Outbox => "outbox", +// }] +// ); +// } +// } + +// #[tokio::test] +// async fn test_mediation_deny_response_for_sender_requester_unmatch() { +// let state = setup(); + +// let msg = Message::build( +// "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), +// MEDIATE_REQUEST_DIC_1_0.to_string(), +// json!(MediationRequest { +// id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), +// message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), +// did: "did:key:unknown".to_string(), +// services: [MediatorService::Inbox, MediatorService::Outbox] +// .into_iter() +// .collect(), +// ..Default::default() +// }), +// ) +// .header("return-route".into(), json!("all")) +// .to(_mediator_did(&state)) +// .from(_edge_did()) +// .finalize(); + +// let response = process_plain_mediation_request_over_dics(Arc::clone(&state), msg) +// .await +// .unwrap() +// .expect("Response should not be None"); + +// assert_eq!(response.clone().type_, MEDIATE_DENY_DIC_1_0); +// assert_eq!(response.clone().from.unwrap(), _mediator_did(&state)); +// assert_eq!(response.to.clone().unwrap(), [_edge_did()]); + +// let mediation_deny: MediationDeny = serde_json::from_value(json!(response)).unwrap(); +// assert_eq!(mediation_deny.message_type, MEDIATE_DENY_DIC_1_0); +// } + +// #[tokio::test] +// async fn test_bad_request_on_invalid_payload_content_type() { +// let state = setup(); + +// let msg = Message::build( +// "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), +// MEDIATE_REQUEST_DIC_1_0.to_string(), +// json!(MediationRequest { +// id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), +// message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), +// did: _edge_did(), +// services: [MediatorService::Inbox, MediatorService::Outbox] +// .into_iter() +// .collect(), +// ..Default::default() +// }), +// ) +// .header("return-route".into(), json!("all")) +// .to(_mediator_did(&state)) +// .from(_edge_did()) +// .finalize(); + +// let response = process_plain_mediation_request_over_dics(Arc::clone(&state), msg).await; + +// assert_eq!( +// response.unwrap_err(), +// MediationError::NotDidcommEncryptedPayload +// ) +// } + +// #[tokio::test] +// async fn test_bad_request_on_unpacking_failure() { +// let (app, state) = setup(); + +// let msg = Message::build( +// "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), +// MEDIATE_REQUEST_DIC_1_0.to_string(), +// json!(MediationRequest { +// id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), +// message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), +// did: _edge_did(), +// services: [MediatorService::Inbox, MediatorService::Outbox] +// .into_iter() +// .collect(), +// ..Default::default() +// }), +// ) +// .header("return-route".into(), json!("all")) +// .to(_edge_did()) +// .from(_edge_did()) +// .finalize(); + +// // Pack for edge instead of mediator +// let packed_msg = _edge_pack_message(&state, &msg, Some(_edge_did()), _edge_did()) +// .await +// .unwrap(); + +// // Send request +// let response = app +// .oneshot( +// Request::builder() +// .uri(String::from("/")) +// .method(Method::POST) +// .header(CONTENT_TYPE, "application/didcomm-encrypted+json") +// .body(Body::from(packed_msg)) +// .unwrap(), +// ) +// .await +// .unwrap(); + +// assert_eq!(response.status(), StatusCode::BAD_REQUEST); +// assert_eq!( +// response.headers().get(CONTENT_TYPE).unwrap(), +// "application/json" +// ); + +// let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); +// let body: Value = serde_json::from_slice(&body).unwrap(); + +// assert_eq!( +// json_canon::to_string(&body).unwrap(), +// json_canon::to_string(&MediationError::MessageUnpackingFailure.json().0).unwrap() +// ) +// } + +// #[tokio::test] +// async fn test_bad_request_on_invalid_jwm_header_message_type() { +// let (app, state) = setup(); + +// let msg = Message::build( +// "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), +// "invalid-message-type".to_string(), +// json!(MediationRequest { +// id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), +// message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), +// did: _edge_did(), +// services: [MediatorService::Inbox, MediatorService::Outbox] +// .into_iter() +// .collect(), +// ..Default::default() +// }), +// ) +// .header("return-route".into(), json!("all")) +// .to(_mediator_did(&state)) +// .from(_edge_did()) +// .finalize(); + +// let packed_msg = _edge_pack_message(&state, &msg, Some(_edge_did()), _mediator_did(&state)) +// .await +// .unwrap(); + +// // Send request +// let response = app +// .oneshot( +// Request::builder() +// .uri(String::from("/")) +// .method(Method::POST) +// .header(CONTENT_TYPE, "application/didcomm-encrypted+json") +// .body(Body::from(packed_msg)) +// .unwrap(), +// ) +// .await +// .unwrap(); + +// assert_eq!(response.status(), StatusCode::BAD_REQUEST); +// assert_eq!( +// response.headers().get(CONTENT_TYPE).unwrap(), +// "application/json" +// ); + +// let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); +// let body: Value = serde_json::from_slice(&body).unwrap(); + +// assert_eq!( +// json_canon::to_string(&body).unwrap(), +// json_canon::to_string(&MediationError::InvalidMessageType.json().0).unwrap() +// ) +// } + +// #[tokio::test] +// async fn test_bad_request_on_missing_return_route_decoration() { +// let state = setup(); + +// let msg = Message::build( +// "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), +// MEDIATE_REQUEST_DIC_1_0.to_string(), +// json!(MediationRequest { +// id: "urn:uuid:ff5a4c85-0df4-4fbe-88ce-fcd2d321a06d".to_string(), +// message_type: MEDIATE_REQUEST_DIC_1_0.to_string(), +// did: _edge_did(), +// services: [MediatorService::Inbox, MediatorService::Outbox] +// .into_iter() +// .collect(), +// ..Default::default() +// }), +// ) +// .to(_mediator_did(&state)) +// .from(_edge_did()) +// .finalize(); + +// let response = process_plain_mediation_request_over_dics(Arc::clone(&state), msg).await; + +// assert_eq!( +// response.unwrap_err(), +// MediationError::NoReturnRouteAllDecoration +// ) +// } + +// #[tokio::test] +// async fn test_bad_request_on_non_mediate_request_payload() { +// let state = setup(); + +// let msg = Message::build( +// "urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(), +// MEDIATE_REQUEST_DIC_1_0.to_string(), +// json!("not-mediate-request"), +// ) +// .header("return-route".into(), json!("all")) +// .to(_mediator_did(&state)) +// .from(_edge_did()) +// .finalize(); + +// let response = process_plain_mediation_request_over_dics(Arc::clone(&state), msg).await; + +// assert_eq!( +// response.unwrap_err(), +// MediationError::UnexpectedMessageFormat +// ) +// } + +// //------------------------------------------------------------------------ +// // Helpers --------------------------------------------------------------- +// //------------------------------------------------------------------------ + +// fn _inspect_dic_tags(vdic: &[CompactDIC]) -> Vec<&'static str> { +// let mut tags: Vec<_> = vdic +// .iter() +// .map(|dic| match dic { +// CompactDIC::Inbox(_) => "inbox", +// CompactDIC::Outbox(_) => "outbox", +// }) +// .collect(); + +// tags.sort(); +// tags +// } +// } diff --git a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/model/coord.rs b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/model/coord.rs index fa2d58f0..56f91d6e 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/model/coord.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/model/coord.rs @@ -3,7 +3,7 @@ use serde::{de::Error, Deserialize, Deserializer, Serialize}; use crate::constants::MEDIATE_REQUEST_2_0; #[cfg(feature = "stateless")] -use super::stateless::coord::MediationRequest as StatelessMediationRequest; +use crate::model::stateless::coord::MediationRequest as StatelessMediationRequest; #[cfg(feature = "stateful")] use super::stateful::coord::MediationRequest as StatefulMediationRequest; @@ -30,7 +30,7 @@ impl MediationRequest { where D: Deserializer<'de>, { - use crate::constant::MEDIATE_REQUEST_DIC_1_0; + use crate::constants::MEDIATE_REQUEST_DIC_1_0; match StatelessMediationRequest::deserialize(deserializer)? { mr if mr.message_type == MEDIATE_REQUEST_DIC_1_0 => Ok(mr), diff --git a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/model/mod.rs b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/model/mod.rs index 3296b1fe..9de2335d 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/model/mod.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/model/mod.rs @@ -2,5 +2,5 @@ pub mod coord; #[cfg(feature = "stateful")] pub mod stateful; -#[cfg(feature = "stateless")] +// #[cfg(feature = "stateless")] pub mod stateless; diff --git a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/model/stateless/coord.rs b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/model/stateless/coord.rs index bd998fe5..bd9ba81d 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/model/stateless/coord.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/model/stateless/coord.rs @@ -28,13 +28,13 @@ pub enum MediatorService { #[serde(rename_all = "camelCase")] pub struct MediationRequest { /// Uniquely identifies a mediation request message. - #[serde(rename = "@id")] + #[serde(rename = "id")] pub id: String, /// References the protocol URI of this concept. /// /// Typically `https://didcomm.org/coordinate-mediation/dic/1.0/mediate-request` - #[serde(rename = "@type")] + #[serde(rename = "type")] pub message_type: String, /// Edge agent's decentralized identifier. @@ -65,13 +65,13 @@ pub struct MediationRequest { #[serde(rename_all = "camelCase")] pub struct MediationGrant { /// Uniquely identifies a mediation grant message. - #[serde(rename = "@id")] + #[serde(rename = "id")] pub id: String, /// References the protocol URI of this concept. /// /// Typically `https://didcomm.org/coordinate-mediation/dic/1.0/mediate-grant` - #[serde(rename = "@type")] + #[serde(rename = "type")] pub message_type: String, /// Mediator's endpoint. @@ -96,13 +96,13 @@ pub struct MediationGrant { #[serde(rename_all = "camelCase")] pub struct MediationDeny { /// Uniquely identifies a mediation deny message. - #[serde(rename = "@id")] + #[serde(rename = "id")] pub id: String, /// References the protocol URI of this concept. /// /// Typically `https://didcomm.org/coordinate-mediation/dic/1.0/mediate-deny` - #[serde(rename = "@type")] + #[serde(rename = "type")] pub message_type: String, /// Dynamic properties. @@ -116,7 +116,7 @@ mod tests { use serde_json::json; - use shared::constants::*; + use crate::constants::*; #[test] fn can_serialize_mediation_request_message() { @@ -131,8 +131,8 @@ mod tests { }; let expected = json!({ - "@id": "id_alice_mediation_request", - "@type": "https://didcomm.org/coordinate-mediation/dic/1.0/mediate-request", + "id": "id_alice_mediation_request", + "type": "https://didcomm.org/coordinate-mediation/dic/1.0/mediate-request", "did": "did:key:alice_identity_pub@alice_mediator", "services": ["inbox", "outbox"] }); @@ -146,8 +146,8 @@ mod tests { #[test] fn can_deserialize_mediation_request_message() { let msg = r#"{ - "@id": "id_alice_mediation_request", - "@type": "https://didcomm.org/coordinate-mediation/dic/1.0/mediate-request", + "id": "id_alice_mediation_request", + "type": "https://didcomm.org/coordinate-mediation/dic/1.0/mediate-request", "did": "did:key:alice_identity_pub@alice_mediator", "services": ["inbox", "outbox"], "antiSpam": { @@ -228,8 +228,8 @@ mod tests { }; let expected = json!({ - "@id": "id_alice_mediation_grant", - "@type": "https://didcomm.org/coordinate-mediation/dic/1.0/mediate-grant", + "id": "id_alice_mediation_grant", + "type": "https://didcomm.org/coordinate-mediation/dic/1.0/mediate-grant", "endpoint": "https://alice-mediator.com", "dic": ["outbox:alice_out_opaque_dic", "inbox:alice_in_opaque_dic"] }); @@ -243,8 +243,8 @@ mod tests { #[test] fn can_deserialize_mediation_grant_message() { let msg = r#"{ - "@id": "id_alice_mediation_grant", - "@type": "https://didcomm.org/coordinate-mediation/dic/1.0/mediate-grant", + "id": "id_alice_mediation_grant", + "type": "https://didcomm.org/coordinate-mediation/dic/1.0/mediate-grant", "endpoint": "https://alice-mediator.com", "dic": ["outbox:alice_out_opaque_dic", "inbox:alice_in_opaque_dic"] }"#; @@ -281,8 +281,8 @@ mod tests { }; let expected = json!({ - "@id": "id_alice_mediation_deny", - "@type": "https://didcomm.org/coordinate-mediation/dic/1.0/mediate-deny" + "id": "id_alice_mediation_deny", + "type": "https://didcomm.org/coordinate-mediation/dic/1.0/mediate-deny" }); assert_eq!( @@ -294,8 +294,8 @@ mod tests { #[test] fn can_deserialize_mediation_deny_message() { let msg = r#"{ - "@id": "id_alice_mediation_deny", - "@type": "https://didcomm.org/coordinate-mediation/dic/1.0/mediate-deny" + "id": "id_alice_mediation_deny", + "type": "https://didcomm.org/coordinate-mediation/dic/1.0/mediate-deny" }"#; // Assert deserialization diff --git a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/model/stateless/dic.rs b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/model/stateless/dic.rs index a01439ce..154e7060 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/model/stateless/dic.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/model/stateless/dic.rs @@ -67,6 +67,7 @@ pub struct DDICPayload { /// Can sign payloads into JWTs pub trait JwtAssertable: Serialize { + #[allow(unused)] /// Sign into JWT fn sign(&self, jwk: &Jwk, kid: Option) -> Result; @@ -122,7 +123,7 @@ impl CompactDIC { macro_rules! compact_dic_variant_serder { ($S: ident) => { - paste::paste! { + paste::item! { fn [](value: &String, serializer: S) -> Result where S: Serializer, @@ -153,17 +154,18 @@ impl CompactDIC { #[cfg(test)] mod tests { use super::*; - use crate::util::{self, MockFileSystem}; use did_utils::crypto::ToPublic; fn setup() -> Jwk { - let mut mock_fs = MockFileSystem; - - let diddoc = util::read_diddoc(&mock_fs, "").unwrap(); - let (_, pubkey) = util::extract_assertion_key(&diddoc).unwrap(); - - let keystore = util::read_keystore(&mut mock_fs, "").unwrap(); - keystore.find_keypair(&pubkey).unwrap() + serde_json::from_str( + r#"{ + "kty": "OKP", + "crv": "Ed25519", + "x": "Z0GqpN71rMcnAkky6_J6Bfknr8B-TBsekG3qdI0EQX4", + "d": "fI1u4riKKd99eox08GlThknq-vEJXcKBI28aiUqArLo" + }"#, + ) + .unwrap() } #[test] diff --git a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/plugin.rs b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/plugin.rs index 3aab4d69..a8afeba5 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/plugin.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/plugin.rs @@ -14,6 +14,7 @@ struct KeylistQueryHandler; #[async_trait] impl MessageHandler for MediateRequestHandler { + #[cfg(feature = "stateful")] async fn handle( &self, state: Arc, @@ -23,6 +24,17 @@ impl MessageHandler for MediateRequestHandler { .await .map_err(|e| e.into_response()) } + + #[cfg(feature = "stateless")] + async fn handle( + &self, + state: Arc, + msg: Message, + ) -> Result, Response> { + crate::handler::stateless::process_plain_mediation_request_over_dics(state, message) + .await + .map_err(|e| e.into_response()) + } } #[async_trait] diff --git a/crates/web-plugins/didcomm-messaging/src/did_rotation/did_rotation.rs b/crates/web-plugins/didcomm-messaging/src/did_rotation/did_rotation.rs deleted file mode 100644 index 582d3016..00000000 --- a/crates/web-plugins/didcomm-messaging/src/did_rotation/did_rotation.rs +++ /dev/null @@ -1,324 +0,0 @@ -use super::errors::RotationError; -use axum::response::{IntoResponse, Response}; -use database::{Repository, RepositoryError}; -use did_utils::didcore::Document as DidDocument; -use didcomm::{FromPrior, Message}; -use mongodb::bson::doc; -use shared::{repository::entity::Connection, utils::resolvers::LocalDIDResolver}; -use std::sync::Arc; - -/// https://identity.foundation/didcomm-messaging/spec/#did-rotation -pub async fn did_rotation( - msg: Message, - connection_repos: &Arc>, -) -> Result<(), Response> { - // Check if from_prior is none - if msg.from_prior.is_none() { - return Ok(()); - } - let jwt = msg.from_prior.unwrap(); - let did_resolver = LocalDIDResolver::new(&DidDocument::default()); - - // decode and validate jwt signature - let (from_prior, _kid) = FromPrior::unpack(&jwt, &did_resolver) - .await - .map_err(|_| RotationError::InvalidFromPrior.json().into_response())?; - let prev = from_prior.iss; - - // validate if did is known - let _ = match connection_repos - .find_one_by(doc! {"client_did": &prev}) - .await - .unwrap() - { - Some(mut connection) => { - // get new did for communication, if empty then we end the relationship - let new = from_prior.sub; - - if new.is_empty() { - let id = connection.id.unwrap_or_default(); - return connection_repos - .delete_one(id) - .await - .map_err(|_| RotationError::TargetNotFound.json().into_response()); - } - - let did_index = connection.keylist.iter().position(|did| did == &prev); - - if did_index.is_some() { - connection.keylist.swap_remove(did_index.unwrap()); - - connection.keylist.push(new.clone()); - } else { - // scenario in which there is rotation prior to keylist update - connection.keylist.push(new.clone()); - } - - // store updated connection - let _confirmations: Result = match connection_repos - .update(Connection { - client_did: new, - ..connection - }) - .await - { - Ok(conn) => Ok(conn), - Err(_) => return Err(RotationError::RepositoryError.json().into_response()), - }; - } - - None => { - return Err(RotationError::UnknownIssuer.json().into_response())?; - } - }; - Ok(()) -} - -#[cfg(test)] -mod test { - use crate::constants::DIDCOMM_ENCRYPTED_MIME_TYPE; - use std::{sync::Arc, vec}; - - use did_utils::{didcore::Document, jwk::Jwk}; - use didcomm::secrets::SecretsResolver; - use mongodb::bson::doc; - - use keystore::{tests::MockKeyStore, Secrets}; - use shared::{ - repository::{ - entity::Connection, - tests::{MockConnectionRepository, MockMessagesRepository}, - }, - state::{AppState, AppStateRepository}, - utils::resolvers::{LocalDIDResolver, LocalSecretsResolver}, - }; - - pub fn prev_did() -> String { - "did:key:z6MkrQT3VKYGkbPaYuJeBv31gNgpmVtRWP5yTocLDBgPpayM".to_string() - } - pub fn new_did() -> String { - "did:key:z6MkqvgpxveKbuygKXnoRcD3jtLTJLgv7g6asLGLsoC4sUEp".to_string() - } - pub fn setup() -> Arc { - let public_domain = String::from("http://alice-mediator.com"); - - let keys = vec![ - Secrets { - id: None, - kid: String::from("did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0#key-1"), - secret_material: serde_json::from_str( - r#"{ - "kty": "OKP", - "crv": "Ed25519", - "x": "CaDmpOjPAiMWfdzBcK2pLyJAER6xvdhDl2dro6BoilQ", - "d": "vp0WuZNeCsoXYj94738e0gwi_PLF7VIutNCrFVNx--0" - }"#, - ) - .unwrap(), - }, - Secrets { - id: None, - kid: String::from("did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0#key-2"), - secret_material: serde_json::from_str( - r#"{ - "kty": "OKP", - "crv": "X25519", - "x": "SQ_7useLAjGf66XAwQWuBuSv9PdD_wB4TJQ6w38nFwQ", - "d": "kxUXT-2TOa6F6xk2ojQgJlT3xWq0aCA9j-BW4VB5_A8" - }"#, - ) - .unwrap(), - }, - ]; - - let diddoc = didoc(); - let repository = AppStateRepository { - connection_repository: Arc::new(MockConnectionRepository::from(_initial_connections())), - keystore: Arc::new(MockKeyStore::new(keys)), - message_repository: Arc::new(MockMessagesRepository::from(vec![])), - }; - - let state = - Arc::new(AppState::from(public_domain, diddoc, None, Some(repository)).unwrap()); - - state - } - fn _initial_connections() -> Vec { - let _recipient_did = prev_did(); - - let connections = format!( - r##"[ - {{ - "_id": {{ - "$oid": "6580701fd2d92bb3cd291b2a" - }}, - - "client_did": "{_recipient_did}", - "mediator_did": "did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0", - "routing_did": "did:key:generated", - "keylist": [ - "{_recipient_did}" - ] - }} - ]"## - ); - - serde_json::from_str(&connections).unwrap() - } - - use didcomm::{FromPrior, Message}; - use serde_json::json; - use uuid::Uuid; - - use super::did_rotation; - - fn didoc() -> Document { - let doc: did_utils::didcore::Document = serde_json::from_str( - r##"{ - "@context": [ - "https://www.w3.org/ns/did/v1", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0", - "alsoKnownAs": [ - "did:peer:3zQmNVZUh4qgAxSWhpeGhJVW3HHHU7MZZbZbQ4Vc43madsSf" - ], - "verificationMethod": [ - { - "id": "#key-1", - "type": "JsonWebKey2020", - "controller": "did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0", - "publicKeyJwk": { - "kty": "OKP", - "crv": "Ed25519", - "x": "CaDmpOjPAiMWfdzBcK2pLyJAER6xvdhDl2dro6BoilQ" - } - }, - { - "id": "#key-2", - "type": "JsonWebKey2020", - "controller": "did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0", - "publicKeyJwk": { - "kty": "OKP", - "crv": "X25519", - "x": "SQ_7useLAjGf66XAwQWuBuSv9PdD_wB4TJQ6w38nFwQ" - } - } - ], - "authentication": [ - "#key-1" - ], - "keyAgreement": [ - "#key-2" - ], - "service": [ - { - "id": "#didcomm", - "type": "DIDCommMessaging", - "serviceEndpoint": { - "accept": [ - "didcomm/v2" - ], - "routingKeys": [], - "uri": "http://alice-mediator.com/" - } - } - ] - }"##, - ) - .unwrap(); - doc - } - - async fn test_jwt_data() -> String { - pub fn prev_secrets_resolver() -> impl SecretsResolver { - let secret_id = "did:key:z6MkrQT3VKYGkbPaYuJeBv31gNgpmVtRWP5yTocLDBgPpayM#z6MkrQT3VKYGkbPaYuJeBv31gNgpmVtRWP5yTocLDBgPpayM"; - let secret_material: Jwk = serde_json::from_str( - r#"{ - "kty": "OKP", - "crv": "Ed25519", - "x": "sZPvulKOXCES3D8Eya3LVnlgOpEaBohCqZ7emD8VXAA", - "d": "kUKFMD3RCZpk556fG0hx9GUrmdvb8t7k3TktPXCi4CY" - }"#, - ) - .unwrap(); - - let secret = Secrets { - id: None, - kid: secret_id.into(), - secret_material, - }; - - let keystore = MockKeyStore::new(vec![secret]); - LocalSecretsResolver::new(Arc::new(keystore)) - } - - let from_prior = FromPrior { - iss: prev_did(), - sub: new_did(), - aud: None, - exp: None, - nbf: None, - iat: None, - jti: None, - }; - - let did_resolver = LocalDIDResolver::new(&didoc()); - let kid = "did:key:z6MkrQT3VKYGkbPaYuJeBv31gNgpmVtRWP5yTocLDBgPpayM#z6MkrQT3VKYGkbPaYuJeBv31gNgpmVtRWP5yTocLDBgPpayM"; - let (jwt, _kid) = from_prior - .pack(Some(&kid), &did_resolver, &prev_secrets_resolver()) - .await - .unwrap(); - jwt - } - - fn test_message_payload(jwt: String) -> Message { - let msg = Message::build( - Uuid::new_v4().to_string(), - "https://didcomm.org/coordinate-mediation/2.0/keylist-update".to_owned(), - json!({"updates": [ - { - "recipient_did": "did:key:z6MkfyTREjTxQ8hUwSwBPeDHf3uPL3qCjSSuNPwsyMpWUGH7", - "action": "add" - }, - { - "recipient_did": "did:key:alice_identity_pub2@alice_mediator", - "action": "remove" - } - ]}), - ) - .header("return_route".into(), json!("all")) - .to("did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0".to_string()) - .from(new_did()) - .from_prior(jwt) - .finalize(); - msg - } - - #[tokio::test] - async fn unit_test_on_did_rotation() { - let jwt = test_jwt_data().await; - let state = setup(); - let AppStateRepository { - connection_repository, - .. - } = state.repository.as_ref().unwrap(); - - let msg = test_message_payload(jwt); - did_rotation(msg, &connection_repository).await.unwrap(); - - // assert if did was rotated on mediator's site - let _ = match connection_repository - .find_one_by(doc! {"client_did": new_did()}) - .await - .unwrap() - { - Some(conn) => { - assert_eq!(conn.client_did, new_did()) - } - None => { - panic!("Rotation Error") - } - }; - } -} diff --git a/crates/web-plugins/didcomm-messaging/src/did_rotation/mod.rs b/crates/web-plugins/didcomm-messaging/src/did_rotation/mod.rs index 45871d5a..a56b4c1b 100644 --- a/crates/web-plugins/didcomm-messaging/src/did_rotation/mod.rs +++ b/crates/web-plugins/didcomm-messaging/src/did_rotation/mod.rs @@ -1,2 +1,325 @@ -pub mod did_rotation; pub mod errors; + +use axum::response::{IntoResponse, Response}; +use database::{Repository, RepositoryError}; +use did_utils::didcore::Document as DidDocument; +use didcomm::{FromPrior, Message}; +use errors::RotationError; +use mongodb::bson::doc; +use shared::{repository::entity::Connection, utils::resolvers::LocalDIDResolver}; +use std::sync::Arc; + +/// https://identity.foundation/didcomm-messaging/spec/#did-rotation +pub async fn did_rotation( + msg: Message, + connection_repos: &Arc>, +) -> Result<(), Response> { + // Check if from_prior is none + if msg.from_prior.is_none() { + return Ok(()); + } + let jwt = msg.from_prior.unwrap(); + let did_resolver = LocalDIDResolver::new(&DidDocument::default()); + + // decode and validate jwt signature + let (from_prior, _kid) = FromPrior::unpack(&jwt, &did_resolver) + .await + .map_err(|_| RotationError::InvalidFromPrior.json().into_response())?; + let prev = from_prior.iss; + + // validate if did is known + let _ = match connection_repos + .find_one_by(doc! {"client_did": &prev}) + .await + .unwrap() + { + Some(mut connection) => { + // get new did for communication, if empty then we end the relationship + let new = from_prior.sub; + + if new.is_empty() { + let id = connection.id.unwrap_or_default(); + return connection_repos + .delete_one(id) + .await + .map_err(|_| RotationError::TargetNotFound.json().into_response()); + } + + let did_index = connection.keylist.iter().position(|did| did == &prev); + + if did_index.is_some() { + connection.keylist.swap_remove(did_index.unwrap()); + + connection.keylist.push(new.clone()); + } else { + // scenario in which there is rotation prior to keylist update + connection.keylist.push(new.clone()); + } + + // store updated connection + let _confirmations: Result = match connection_repos + .update(Connection { + client_did: new, + ..connection + }) + .await + { + Ok(conn) => Ok(conn), + Err(_) => return Err(RotationError::RepositoryError.json().into_response()), + }; + } + + None => { + return Err(RotationError::UnknownIssuer.json().into_response())?; + } + }; + Ok(()) +} + +#[cfg(test)] +mod test { + use std::{sync::Arc, vec}; + + use did_utils::{didcore::Document, jwk::Jwk}; + use didcomm::secrets::SecretsResolver; + use mongodb::bson::doc; + + use keystore::{tests::MockKeyStore, Secrets}; + use shared::{ + repository::{ + entity::Connection, + tests::{MockConnectionRepository, MockMessagesRepository}, + }, + state::{AppState, AppStateRepository}, + utils::resolvers::{LocalDIDResolver, LocalSecretsResolver}, + }; + + pub fn prev_did() -> String { + "did:key:z6MkrQT3VKYGkbPaYuJeBv31gNgpmVtRWP5yTocLDBgPpayM".to_string() + } + pub fn new_did() -> String { + "did:key:z6MkqvgpxveKbuygKXnoRcD3jtLTJLgv7g6asLGLsoC4sUEp".to_string() + } + pub fn setup() -> Arc { + let public_domain = String::from("http://alice-mediator.com"); + + let keys = vec![ + Secrets { + id: None, + kid: String::from("did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0#key-1"), + secret_material: serde_json::from_str( + r#"{ + "kty": "OKP", + "crv": "Ed25519", + "x": "CaDmpOjPAiMWfdzBcK2pLyJAER6xvdhDl2dro6BoilQ", + "d": "vp0WuZNeCsoXYj94738e0gwi_PLF7VIutNCrFVNx--0" + }"#, + ) + .unwrap(), + }, + Secrets { + id: None, + kid: String::from("did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0#key-2"), + secret_material: serde_json::from_str( + r#"{ + "kty": "OKP", + "crv": "X25519", + "x": "SQ_7useLAjGf66XAwQWuBuSv9PdD_wB4TJQ6w38nFwQ", + "d": "kxUXT-2TOa6F6xk2ojQgJlT3xWq0aCA9j-BW4VB5_A8" + }"#, + ) + .unwrap(), + }, + ]; + + let diddoc = didoc(); + let repository = AppStateRepository { + connection_repository: Arc::new(MockConnectionRepository::from(_initial_connections())), + keystore: Arc::new(MockKeyStore::new(keys)), + message_repository: Arc::new(MockMessagesRepository::from(vec![])), + }; + + let state = + Arc::new(AppState::from(public_domain, diddoc, None, Some(repository)).unwrap()); + + state + } + fn _initial_connections() -> Vec { + let _recipient_did = prev_did(); + + let connections = format!( + r##"[ + {{ + "_id": {{ + "$oid": "6580701fd2d92bb3cd291b2a" + }}, + + "client_did": "{_recipient_did}", + "mediator_did": "did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0", + "routing_did": "did:key:generated", + "keylist": [ + "{_recipient_did}" + ] + }} + ]"## + ); + + serde_json::from_str(&connections).unwrap() + } + + use didcomm::{FromPrior, Message}; + use serde_json::json; + use uuid::Uuid; + + use super::did_rotation; + + fn didoc() -> Document { + let doc: did_utils::didcore::Document = serde_json::from_str( + r##"{ + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0", + "alsoKnownAs": [ + "did:peer:3zQmNVZUh4qgAxSWhpeGhJVW3HHHU7MZZbZbQ4Vc43madsSf" + ], + "verificationMethod": [ + { + "id": "#key-1", + "type": "JsonWebKey2020", + "controller": "did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0", + "publicKeyJwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "CaDmpOjPAiMWfdzBcK2pLyJAER6xvdhDl2dro6BoilQ" + } + }, + { + "id": "#key-2", + "type": "JsonWebKey2020", + "controller": "did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0", + "publicKeyJwk": { + "kty": "OKP", + "crv": "X25519", + "x": "SQ_7useLAjGf66XAwQWuBuSv9PdD_wB4TJQ6w38nFwQ" + } + } + ], + "authentication": [ + "#key-1" + ], + "keyAgreement": [ + "#key-2" + ], + "service": [ + { + "id": "#didcomm", + "type": "DIDCommMessaging", + "serviceEndpoint": { + "accept": [ + "didcomm/v2" + ], + "routingKeys": [], + "uri": "http://alice-mediator.com/" + } + } + ] + }"##, + ) + .unwrap(); + doc + } + + async fn test_jwt_data() -> String { + pub fn prev_secrets_resolver() -> impl SecretsResolver { + let secret_id = "did:key:z6MkrQT3VKYGkbPaYuJeBv31gNgpmVtRWP5yTocLDBgPpayM#z6MkrQT3VKYGkbPaYuJeBv31gNgpmVtRWP5yTocLDBgPpayM"; + let secret_material: Jwk = serde_json::from_str( + r#"{ + "kty": "OKP", + "crv": "Ed25519", + "x": "sZPvulKOXCES3D8Eya3LVnlgOpEaBohCqZ7emD8VXAA", + "d": "kUKFMD3RCZpk556fG0hx9GUrmdvb8t7k3TktPXCi4CY" + }"#, + ) + .unwrap(); + + let secret = Secrets { + id: None, + kid: secret_id.into(), + secret_material, + }; + + let keystore = MockKeyStore::new(vec![secret]); + LocalSecretsResolver::new(Arc::new(keystore)) + } + + let from_prior = FromPrior { + iss: prev_did(), + sub: new_did(), + aud: None, + exp: None, + nbf: None, + iat: None, + jti: None, + }; + + let did_resolver = LocalDIDResolver::new(&didoc()); + let kid = "did:key:z6MkrQT3VKYGkbPaYuJeBv31gNgpmVtRWP5yTocLDBgPpayM#z6MkrQT3VKYGkbPaYuJeBv31gNgpmVtRWP5yTocLDBgPpayM"; + let (jwt, _kid) = from_prior + .pack(Some(&kid), &did_resolver, &prev_secrets_resolver()) + .await + .unwrap(); + jwt + } + + fn test_message_payload(jwt: String) -> Message { + let msg = Message::build( + Uuid::new_v4().to_string(), + "https://didcomm.org/coordinate-mediation/2.0/keylist-update".to_owned(), + json!({"updates": [ + { + "recipient_did": "did:key:z6MkfyTREjTxQ8hUwSwBPeDHf3uPL3qCjSSuNPwsyMpWUGH7", + "action": "add" + }, + { + "recipient_did": "did:key:alice_identity_pub2@alice_mediator", + "action": "remove" + } + ]}), + ) + .header("return_route".into(), json!("all")) + .to("did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0".to_string()) + .from(new_did()) + .from_prior(jwt) + .finalize(); + msg + } + + #[tokio::test] + async fn unit_test_on_did_rotation() { + let jwt = test_jwt_data().await; + let state = setup(); + let AppStateRepository { + connection_repository, + .. + } = state.repository.as_ref().unwrap(); + + let msg = test_message_payload(jwt); + did_rotation(msg, &connection_repository).await.unwrap(); + + // assert if did was rotated on mediator's site + let _ = match connection_repository + .find_one_by(doc! {"client_did": new_did()}) + .await + .unwrap() + { + Some(conn) => { + assert_eq!(conn.client_did, new_did()) + } + None => { + panic!("Rotation Error") + } + }; + } +} diff --git a/crates/web-plugins/didcomm-messaging/src/midlw.rs b/crates/web-plugins/didcomm-messaging/src/midlw.rs index 31839e4d..a8ca8df6 100644 --- a/crates/web-plugins/didcomm-messaging/src/midlw.rs +++ b/crates/web-plugins/didcomm-messaging/src/midlw.rs @@ -12,7 +12,7 @@ use std::sync::Arc; // use super::{error::MediationError, AppState}; use crate::{ constants::{DIDCOMM_ENCRYPTED_MIME_TYPE, DIDCOMM_ENCRYPTED_SHORT_MIME_TYPE}, - did_rotation::did_rotation::did_rotation, + did_rotation::did_rotation, error::Error, }; use shared::{ From 0f892b01e15408d11685bbd8b954200136dedbac Mon Sep 17 00:00:00 2001 From: Hermann Core Date: Mon, 9 Dec 2024 12:18:02 +0100 Subject: [PATCH 2/7] add clippy checks --- crates/filesystem/src/lib.rs | 5 +++-- crates/keystore/src/lib.rs | 11 ++++++---- crates/web-plugins/did-endpoint/src/didgen.rs | 2 +- crates/web-plugins/did-endpoint/src/web.rs | 10 ++++----- .../did-utils/src/methods/peer/errors.rs | 2 +- .../did-utils/src/methods/peer/resolver.rs | 2 +- .../protocols/basic-message/src/handler.rs | 2 +- .../discover-features/src/handler.rs | 21 ++++++++----------- .../protocols/forward/src/handler.rs | 2 +- .../src/handler/stateful.rs | 18 +++++++--------- .../protocols/pickup/src/handler.rs | 17 +++++++-------- .../didcomm-messaging/shared/src/utils.rs | 4 ++-- .../didcomm-messaging/src/midlw.rs | 2 +- crates/web-plugins/oob-messages/src/models.rs | 2 +- src/plugins/manager.rs | 2 +- 15 files changed, 49 insertions(+), 53 deletions(-) diff --git a/crates/filesystem/src/lib.rs b/crates/filesystem/src/lib.rs index a8f04e71..6f98992d 100644 --- a/crates/filesystem/src/lib.rs +++ b/crates/filesystem/src/lib.rs @@ -54,14 +54,15 @@ impl FileSystem for StdFileSystem { let file = OpenOptions::new() .read(true) .write(true) + .truncate(true) .create(true) - .open(&path)?; + .open(path)?; // Acquire an exclusive lock before writing to the file flock(file.as_raw_fd(), FlockArg::LockExclusive) .map_err(|_| IoError::new(ErrorKind::Other, "Error acquiring file lock"))?; - std::fs::write(path, &content).map_err(|_| { + std::fs::write(path, content).map_err(|_| { IoError::new( ErrorKind::Other, "Error saving base64-encoded image to file", diff --git a/crates/keystore/src/lib.rs b/crates/keystore/src/lib.rs index 5fe88c7c..90925166 100644 --- a/crates/keystore/src/lib.rs +++ b/crates/keystore/src/lib.rs @@ -40,6 +40,12 @@ where collection: Collection, } +impl Default for KeyStore { + fn default() -> Self { + Self::new() + } +} + impl KeyStore { /// Create a new keystore with default Secrets type. /// @@ -52,10 +58,7 @@ impl KeyStore { let db_lock = db.write().await; db_lock.collection::("secrets").clone() }; - let collection = tokio::task::block_in_place(|| { - tokio::runtime::Handle::current().block_on(task) - }); - collection + tokio::task::block_in_place(|| tokio::runtime::Handle::current().block_on(task)) }) .clone(); diff --git a/crates/web-plugins/did-endpoint/src/didgen.rs b/crates/web-plugins/did-endpoint/src/didgen.rs index 68910db0..724015f0 100644 --- a/crates/web-plugins/did-endpoint/src/didgen.rs +++ b/crates/web-plugins/did-endpoint/src/didgen.rs @@ -154,7 +154,7 @@ where // Create directory and write the DID document filesystem - .create_dir_all(&storage_dirpath) + .create_dir_all(storage_dirpath) .map_err(|_| Error::PersistenceError)?; filesystem .write(&storage_dirpath.join("did.json"), &pretty_diddoc) diff --git a/crates/web-plugins/did-endpoint/src/web.rs b/crates/web-plugins/did-endpoint/src/web.rs index 88fb7f34..2e1e622b 100644 --- a/crates/web-plugins/did-endpoint/src/web.rs +++ b/crates/web-plugins/did-endpoint/src/web.rs @@ -36,7 +36,7 @@ async fn diddoc(State(state): State>) -> Result Ok(Json(serde_json::from_str(&content).map_err(|_| { + Ok(content) => Ok(Json(serde_json::from_str(content).map_err(|_| { tracing::error!("Unparseable did.json"); StatusCode::NOT_FOUND })?)), @@ -56,7 +56,7 @@ async fn didpop( let diddoc: Document = serde_json::from_value(diddoc_value.clone()).unwrap(); let did_address = diddoc.id.clone(); - let methods = diddoc.verification_method.clone().unwrap_or(vec![]); + let methods = diddoc.verification_method.clone().unwrap_or_default(); // Build verifiable credential (VC) let vc: VerifiableCredential = serde_json::from_value(json!({ @@ -157,15 +157,15 @@ async fn didpop( fn inspect_vm_relationship(diddoc: &Document, vm_id: &str) -> Option { let vrel = [ ( - json!(diddoc.authentication.clone().unwrap_or(vec![])), + json!(diddoc.authentication.clone().unwrap_or_default()), String::from("authentication"), ), ( - json!(diddoc.assertion_method.clone().unwrap_or(vec![])), + json!(diddoc.assertion_method.clone().unwrap_or_default()), String::from("assertionMethod"), ), ( - json!(diddoc.key_agreement.clone().unwrap_or(vec![])), + json!(diddoc.key_agreement.clone().unwrap_or_default()), String::from("keyAgreement"), ), ]; diff --git a/crates/web-plugins/didcomm-messaging/did-utils/src/methods/peer/errors.rs b/crates/web-plugins/didcomm-messaging/did-utils/src/methods/peer/errors.rs index 3ba16fc4..aed377ed 100644 --- a/crates/web-plugins/didcomm-messaging/did-utils/src/methods/peer/errors.rs +++ b/crates/web-plugins/didcomm-messaging/did-utils/src/methods/peer/errors.rs @@ -65,7 +65,7 @@ impl From for DIDResolutionError { impl std::fmt::Display for DIDPeerMethodError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self) // Customize this to format the error as desired + write!(f, "{:?}", self) } } diff --git a/crates/web-plugins/didcomm-messaging/did-utils/src/methods/peer/resolver.rs b/crates/web-plugins/didcomm-messaging/did-utils/src/methods/peer/resolver.rs index 1a525c00..6728220b 100644 --- a/crates/web-plugins/didcomm-messaging/did-utils/src/methods/peer/resolver.rs +++ b/crates/web-plugins/didcomm-messaging/did-utils/src/methods/peer/resolver.rs @@ -35,7 +35,7 @@ impl DIDResolver for DidPeer { error: Some(if !did.starts_with("did:peer:") { DIDResolutionError::MethodNotSupported } else { - err.into() + err }), content_type: None, additional_properties: None, diff --git a/crates/web-plugins/didcomm-messaging/protocols/basic-message/src/handler.rs b/crates/web-plugins/didcomm-messaging/protocols/basic-message/src/handler.rs index 42a51ded..13e47ffb 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/basic-message/src/handler.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/basic-message/src/handler.rs @@ -7,7 +7,7 @@ use std::sync::Arc; // https://didcomm.org/basicmessage/2.0/ pub fn handle_basic_message(_state: Arc, message: Message) -> Response { - if message.extra_headers.get("lang").is_none() { + if !message.extra_headers.contains_key("lang") { return (StatusCode::BAD_REQUEST, "Language is required").into_response(); } diff --git a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs index c6fde57c..36f020ff 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs @@ -32,15 +32,14 @@ pub(crate) async fn handle_query_request( Some(id) => { let id = id.as_str().unwrap_or_default(); - if !id + if id .ends_with(".*") .then(|| { supported - .into_iter() - .find(|protocol| protocol.contains(&id.to_string())) - .is_some() + .iter() + .any(|protocol| protocol.contains(&id.to_string())) }) - .is_some() + .is_none() { disclosed_protocols.insert(id.to_owned()); } @@ -50,13 +49,13 @@ pub(crate) async fn handle_query_request( // stores the full protocol obtained when we have a match with wildcard let mut container: String = Default::default(); - if let Some(id) = parts.get(0) { + if let Some(id) = parts.first() { supported - .into_iter() + .iter() .find(|protocol| protocol.contains(&id.to_string())) .is_some_and(|protocol| { container = protocol.to_string(); - return true; + true }) .then(|| { let parts: Vec<&str> = @@ -88,7 +87,7 @@ pub(crate) async fn handle_query_request( let msg = build_response(disclosed_protocols); Ok(Some(msg)) } else { - return Err(DiscoveryError::QueryNotFound); + Err(DiscoveryError::QueryNotFound) } } else { let msg = build_response(disclosed_protocols); @@ -110,9 +109,7 @@ fn build_response(disclosed_protocols: HashSet) -> Message { } let id = Uuid::new_v4().urn().to_string(); - let msg = Message::build(id, DISCOVER_FEATURE.to_string(), json!(body)).finalize(); - - msg + Message::build(id, DISCOVER_FEATURE.to_string(), json!(body)).finalize() } #[cfg(test)] diff --git a/crates/web-plugins/didcomm-messaging/protocols/forward/src/handler.rs b/crates/web-plugins/didcomm-messaging/protocols/forward/src/handler.rs index cc64de99..2d1a86fc 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/forward/src/handler.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/forward/src/handler.rs @@ -22,7 +22,7 @@ pub(crate) async fn mediator_forward_process( } = state .repository .as_ref() - .ok_or_else(|| ForwardError::InternalServerError)?; + .ok_or(ForwardError::InternalServerError)?; let next = match checks(&message, connection_repository).await.ok() { Some(next) => Ok(next), diff --git a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/stateful.rs b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/stateful.rs index 027e89b9..2a135813 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/stateful.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/stateful.rs @@ -59,20 +59,19 @@ pub(crate) async fn process_mediate_request( .map_err(|_| MediationError::InternalServerError)? { tracing::info!("Sending mediate deny."); - return Ok(Some( + Ok(Some( Message::build( format!("urn:uuid:{}", Uuid::new_v4()), MEDIATE_DENY_2_0.to_string(), json!(MediationDeny { id: format!("urn:uuid:{}", Uuid::new_v4()), message_type: MEDIATE_DENY_2_0.to_string(), - ..Default::default() }), ) .to(sender_did.clone()) .from(mediator_did.clone()) .finalize(), - )); + )) } else { /* Issue mediate grant response */ tracing::info!("Sending mediate grant."); @@ -99,7 +98,7 @@ pub(crate) async fn process_mediate_request( let agreem_keys_secret = Secrets { id: None, - kid: diddoc.key_agreement.get(0).unwrap().clone(), + kid: diddoc.key_agreement.first().unwrap().clone(), secret_material: agreem_keys_jwk, }; @@ -114,7 +113,7 @@ pub(crate) async fn process_mediate_request( let auth_keys_secret = Secrets { id: None, - kid: diddoc.authentication.get(0).unwrap().clone(), + kid: diddoc.authentication.first().unwrap().clone(), secret_material: auth_keys_jwk, }; @@ -132,7 +131,7 @@ pub(crate) async fn process_mediate_request( client_did: sender_did.to_string(), mediator_did: mediator_did.to_string(), keylist: vec!["".to_string()], - routing_did: routing_did, + routing_did, }; // Use store_one to store the sample connection @@ -163,7 +162,6 @@ fn create_mediation_grant(routing_did: &str) -> MediationGrant { body: MediationGrantBody { routing_did: routing_did.to_string(), }, - ..Default::default() } } @@ -233,7 +231,7 @@ pub(crate) async fn process_plain_keylist_update_message( .find_one_by(doc! { "client_did": &sender }) .await .unwrap() - .ok_or_else(|| MediationError::UncoordinatedSender)?; + .ok_or(MediationError::UncoordinatedSender)?; // Prepare handles to relevant collections @@ -351,7 +349,7 @@ pub(crate) async fn process_plain_keylist_query_message( .find_one_by(doc! { "client_did": &sender }) .await .unwrap() - .ok_or_else(|| MediationError::UncoordinatedSender)?; + .ok_or(MediationError::UncoordinatedSender)?; println!("keylist: {:?}", connection); @@ -371,7 +369,7 @@ pub(crate) async fn process_plain_keylist_query_message( let keylist_object = Keylist { id: format!("urn:uuid:{}", Uuid::new_v4()), message_type: KEYLIST_2_0.to_string(), - body: body, + body, additional_properties: None, }; diff --git a/crates/web-plugins/didcomm-messaging/protocols/pickup/src/handler.rs b/crates/web-plugins/didcomm-messaging/protocols/pickup/src/handler.rs index 87c0a2b5..2e2add0d 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/pickup/src/handler.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/pickup/src/handler.rs @@ -86,12 +86,10 @@ pub(crate) async fn handle_delivery_request( let connection = client_connection(&repository, sender_did).await?; let messages = messages(repository, recipient_did, connection, limit as usize).await?; - - let response_builder: MessageBuilder; let id = Uuid::new_v4().urn().to_string(); - if messages.is_empty() { - response_builder = StatusResponse { + let response_builder: MessageBuilder = if messages.is_empty() { + StatusResponse { id: id.as_str(), type_: STATUS_RESPONSE_3_0, body: BodyStatusResponse { @@ -101,7 +99,7 @@ pub(crate) async fn handle_delivery_request( ..Default::default() }, } - .into(); + .into() } else { let mut attachments: Vec = Vec::with_capacity(messages.len()); @@ -117,15 +115,15 @@ pub(crate) async fn handle_delivery_request( attachments.push(attached); } - response_builder = DeliveryResponse { + DeliveryResponse { id: id.as_str(), thid: id.as_str(), type_: MESSAGE_DELIVERY_3_0, body: BodyDeliveryResponse { recipient_did }, attachments, } - .into(); - } + .into() + }; let response = response_builder .to(sender_did.to_owned()) @@ -301,8 +299,7 @@ fn recipients<'a>(recipient_did: Option<&'a str>, connection: &'a Connection) -> fn sender_did(message: &Message) -> Result<&str, PickupError> { message .from - .as_ref() - .map(|did| did.as_str()) + .as_deref() .ok_or(PickupError::MissingSenderDID) } diff --git a/crates/web-plugins/didcomm-messaging/shared/src/utils.rs b/crates/web-plugins/didcomm-messaging/shared/src/utils.rs index af375177..70e01cdf 100644 --- a/crates/web-plugins/didcomm-messaging/shared/src/utils.rs +++ b/crates/web-plugins/didcomm-messaging/shared/src/utils.rs @@ -63,7 +63,7 @@ macro_rules! extract_key_from_diddoc { /// /// if present, return its verification method ID and JWK representation. pub fn extract_authentication_key(diddoc: &Document) -> Option<(String, Jwk)> { - let method = diddoc.authentication.as_ref()?.get(0)?; + let method = diddoc.authentication.as_ref()?.first()?; extract_key_from_diddoc!(VerificationMethodType)(diddoc, method) } @@ -71,7 +71,7 @@ pub fn extract_authentication_key(diddoc: &Document) -> Option<(String, Jwk)> { /// /// if present, return its verification method ID and JWK representation. pub fn extract_agreement_key(diddoc: &Document) -> Option<(String, Jwk)> { - let method = diddoc.key_agreement.as_ref()?.get(0)?; + let method = diddoc.key_agreement.as_ref()?.first()?; extract_key_from_diddoc!(VerificationMethodType)(diddoc, method) } diff --git a/crates/web-plugins/didcomm-messaging/src/midlw.rs b/crates/web-plugins/didcomm-messaging/src/midlw.rs index a8ca8df6..19774e54 100644 --- a/crates/web-plugins/didcomm-messaging/src/midlw.rs +++ b/crates/web-plugins/didcomm-messaging/src/midlw.rs @@ -148,7 +148,7 @@ pub async fn pack_response_message( secrets_resolver: &LocalSecretsResolver, ) -> Result { let from = msg.from.as_ref(); - let to = msg.to.as_ref().and_then(|v| v.get(0)); + let to = msg.to.as_ref().and_then(|v| v.first()); if from.is_none() || to.is_none() { let response = ( diff --git a/crates/web-plugins/oob-messages/src/models.rs b/crates/web-plugins/oob-messages/src/models.rs index 6dd93a74..b3bfff9a 100644 --- a/crates/web-plugins/oob-messages/src/models.rs +++ b/crates/web-plugins/oob-messages/src/models.rs @@ -83,7 +83,7 @@ impl OobMessage { } // Receives server path/port and local storage path and returns a String with the OOB URL. -pub(crate) fn retrieve_or_generate_oob_inv<'a>( +pub(crate) fn retrieve_or_generate_oob_inv( fs: &mut dyn FileSystem, server_public_domain: &str, server_local_port: &str, diff --git a/src/plugins/manager.rs b/src/plugins/manager.rs index 9aec46f5..634e08ef 100644 --- a/src/plugins/manager.rs +++ b/src/plugins/manager.rs @@ -44,7 +44,7 @@ impl<'a> PluginContainer<'a> { pub fn find_plugin(&self, name: &str) -> Option>> { self.plugins.iter().find_map(|arc_plugin| { let plugin = arc_plugin.lock().unwrap(); - (plugin.name() == name).then_some(Arc::clone(&arc_plugin)) + (plugin.name() == name).then_some(Arc::clone(arc_plugin)) }) } From cbd17b7ccab9b73be6c31fd6605df65bd5fa8e0c Mon Sep 17 00:00:00 2001 From: Hermann Core Date: Mon, 9 Dec 2024 12:46:24 +0100 Subject: [PATCH 3/7] remove warnings and add clippy checks to the code base --- .../mediator-coordination/Cargo.toml | 1 + .../mediator-coordination/src/handler/mod.rs | 1 - .../src/handler/stateless.rs | 1 + .../mediator-coordination/src/plugin.rs | 12 - .../protocols/pickup/src/handler.rs | 5 +- .../shared/src/utils/tests_utils.rs | 5 +- .../src/did_rotation/did_rotation.rs | 324 ++++++++++++++++++ .../didcomm-messaging/src/did_rotation/mod.rs | 6 +- 8 files changed, 331 insertions(+), 24 deletions(-) create mode 100644 crates/web-plugins/didcomm-messaging/src/did_rotation/did_rotation.rs diff --git a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/Cargo.toml b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/Cargo.toml index b85efe24..e8e55900 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/Cargo.toml @@ -19,6 +19,7 @@ async-trait.workspace = true serde_json.workspace = true thiserror.workspace = true tracing.workspace = true +cfg-if.workspace = true json-canon.workspace = true didcomm = { workspace = true, features = ["uniffi"] } tokio = { workspace = true, features = ["full"] } diff --git a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/mod.rs b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/mod.rs index bc4772ff..ce59175d 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/mod.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/mod.rs @@ -2,6 +2,5 @@ mod midlw; #[cfg(feature = "stateful")] pub(crate) mod stateful; -#[allow(unexpected_cfgs)] #[cfg(feature = "stateless")] pub(crate) mod stateless; diff --git a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/stateless.rs b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/stateless.rs index b5973860..9128bf80 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/stateless.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/handler/stateless.rs @@ -19,6 +19,7 @@ use shared::{ }; use uuid::Uuid; +#[allow(dead_code)] /// Process a DIC-wise mediation request pub(crate) async fn process_plain_mediation_request_over_dics( state: Arc, diff --git a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/plugin.rs b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/plugin.rs index a8afeba5..3aab4d69 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/plugin.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/src/plugin.rs @@ -14,7 +14,6 @@ struct KeylistQueryHandler; #[async_trait] impl MessageHandler for MediateRequestHandler { - #[cfg(feature = "stateful")] async fn handle( &self, state: Arc, @@ -24,17 +23,6 @@ impl MessageHandler for MediateRequestHandler { .await .map_err(|e| e.into_response()) } - - #[cfg(feature = "stateless")] - async fn handle( - &self, - state: Arc, - msg: Message, - ) -> Result, Response> { - crate::handler::stateless::process_plain_mediation_request_over_dics(state, message) - .await - .map_err(|e| e.into_response()) - } } #[async_trait] diff --git a/crates/web-plugins/didcomm-messaging/protocols/pickup/src/handler.rs b/crates/web-plugins/didcomm-messaging/protocols/pickup/src/handler.rs index 2e2add0d..9b71840a 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/pickup/src/handler.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/pickup/src/handler.rs @@ -297,10 +297,7 @@ fn recipients<'a>(recipient_did: Option<&'a str>, connection: &'a Connection) -> #[inline] fn sender_did(message: &Message) -> Result<&str, PickupError> { - message - .from - .as_deref() - .ok_or(PickupError::MissingSenderDID) + message.from.as_deref().ok_or(PickupError::MissingSenderDID) } #[inline] diff --git a/crates/web-plugins/didcomm-messaging/shared/src/utils/tests_utils.rs b/crates/web-plugins/didcomm-messaging/shared/src/utils/tests_utils.rs index 7ba2b7b5..104f6283 100644 --- a/crates/web-plugins/didcomm-messaging/shared/src/utils/tests_utils.rs +++ b/crates/web-plugins/didcomm-messaging/shared/src/utils/tests_utils.rs @@ -93,10 +93,7 @@ pub mod tests { keystore: Arc::new(MockKeyStore::new(vec![mediator_secret])), }; - let state = - Arc::new(AppState::from(public_domain, diddoc, None, Some(repository)).unwrap()); - - state + Arc::new(AppState::from(public_domain, diddoc, None, Some(repository)).unwrap()) } pub fn _mediator_did(state: &AppState) -> String { diff --git a/crates/web-plugins/didcomm-messaging/src/did_rotation/did_rotation.rs b/crates/web-plugins/didcomm-messaging/src/did_rotation/did_rotation.rs new file mode 100644 index 00000000..582d3016 --- /dev/null +++ b/crates/web-plugins/didcomm-messaging/src/did_rotation/did_rotation.rs @@ -0,0 +1,324 @@ +use super::errors::RotationError; +use axum::response::{IntoResponse, Response}; +use database::{Repository, RepositoryError}; +use did_utils::didcore::Document as DidDocument; +use didcomm::{FromPrior, Message}; +use mongodb::bson::doc; +use shared::{repository::entity::Connection, utils::resolvers::LocalDIDResolver}; +use std::sync::Arc; + +/// https://identity.foundation/didcomm-messaging/spec/#did-rotation +pub async fn did_rotation( + msg: Message, + connection_repos: &Arc>, +) -> Result<(), Response> { + // Check if from_prior is none + if msg.from_prior.is_none() { + return Ok(()); + } + let jwt = msg.from_prior.unwrap(); + let did_resolver = LocalDIDResolver::new(&DidDocument::default()); + + // decode and validate jwt signature + let (from_prior, _kid) = FromPrior::unpack(&jwt, &did_resolver) + .await + .map_err(|_| RotationError::InvalidFromPrior.json().into_response())?; + let prev = from_prior.iss; + + // validate if did is known + let _ = match connection_repos + .find_one_by(doc! {"client_did": &prev}) + .await + .unwrap() + { + Some(mut connection) => { + // get new did for communication, if empty then we end the relationship + let new = from_prior.sub; + + if new.is_empty() { + let id = connection.id.unwrap_or_default(); + return connection_repos + .delete_one(id) + .await + .map_err(|_| RotationError::TargetNotFound.json().into_response()); + } + + let did_index = connection.keylist.iter().position(|did| did == &prev); + + if did_index.is_some() { + connection.keylist.swap_remove(did_index.unwrap()); + + connection.keylist.push(new.clone()); + } else { + // scenario in which there is rotation prior to keylist update + connection.keylist.push(new.clone()); + } + + // store updated connection + let _confirmations: Result = match connection_repos + .update(Connection { + client_did: new, + ..connection + }) + .await + { + Ok(conn) => Ok(conn), + Err(_) => return Err(RotationError::RepositoryError.json().into_response()), + }; + } + + None => { + return Err(RotationError::UnknownIssuer.json().into_response())?; + } + }; + Ok(()) +} + +#[cfg(test)] +mod test { + use crate::constants::DIDCOMM_ENCRYPTED_MIME_TYPE; + use std::{sync::Arc, vec}; + + use did_utils::{didcore::Document, jwk::Jwk}; + use didcomm::secrets::SecretsResolver; + use mongodb::bson::doc; + + use keystore::{tests::MockKeyStore, Secrets}; + use shared::{ + repository::{ + entity::Connection, + tests::{MockConnectionRepository, MockMessagesRepository}, + }, + state::{AppState, AppStateRepository}, + utils::resolvers::{LocalDIDResolver, LocalSecretsResolver}, + }; + + pub fn prev_did() -> String { + "did:key:z6MkrQT3VKYGkbPaYuJeBv31gNgpmVtRWP5yTocLDBgPpayM".to_string() + } + pub fn new_did() -> String { + "did:key:z6MkqvgpxveKbuygKXnoRcD3jtLTJLgv7g6asLGLsoC4sUEp".to_string() + } + pub fn setup() -> Arc { + let public_domain = String::from("http://alice-mediator.com"); + + let keys = vec![ + Secrets { + id: None, + kid: String::from("did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0#key-1"), + secret_material: serde_json::from_str( + r#"{ + "kty": "OKP", + "crv": "Ed25519", + "x": "CaDmpOjPAiMWfdzBcK2pLyJAER6xvdhDl2dro6BoilQ", + "d": "vp0WuZNeCsoXYj94738e0gwi_PLF7VIutNCrFVNx--0" + }"#, + ) + .unwrap(), + }, + Secrets { + id: None, + kid: String::from("did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0#key-2"), + secret_material: serde_json::from_str( + r#"{ + "kty": "OKP", + "crv": "X25519", + "x": "SQ_7useLAjGf66XAwQWuBuSv9PdD_wB4TJQ6w38nFwQ", + "d": "kxUXT-2TOa6F6xk2ojQgJlT3xWq0aCA9j-BW4VB5_A8" + }"#, + ) + .unwrap(), + }, + ]; + + let diddoc = didoc(); + let repository = AppStateRepository { + connection_repository: Arc::new(MockConnectionRepository::from(_initial_connections())), + keystore: Arc::new(MockKeyStore::new(keys)), + message_repository: Arc::new(MockMessagesRepository::from(vec![])), + }; + + let state = + Arc::new(AppState::from(public_domain, diddoc, None, Some(repository)).unwrap()); + + state + } + fn _initial_connections() -> Vec { + let _recipient_did = prev_did(); + + let connections = format!( + r##"[ + {{ + "_id": {{ + "$oid": "6580701fd2d92bb3cd291b2a" + }}, + + "client_did": "{_recipient_did}", + "mediator_did": "did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0", + "routing_did": "did:key:generated", + "keylist": [ + "{_recipient_did}" + ] + }} + ]"## + ); + + serde_json::from_str(&connections).unwrap() + } + + use didcomm::{FromPrior, Message}; + use serde_json::json; + use uuid::Uuid; + + use super::did_rotation; + + fn didoc() -> Document { + let doc: did_utils::didcore::Document = serde_json::from_str( + r##"{ + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0", + "alsoKnownAs": [ + "did:peer:3zQmNVZUh4qgAxSWhpeGhJVW3HHHU7MZZbZbQ4Vc43madsSf" + ], + "verificationMethod": [ + { + "id": "#key-1", + "type": "JsonWebKey2020", + "controller": "did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0", + "publicKeyJwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "CaDmpOjPAiMWfdzBcK2pLyJAER6xvdhDl2dro6BoilQ" + } + }, + { + "id": "#key-2", + "type": "JsonWebKey2020", + "controller": "did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0", + "publicKeyJwk": { + "kty": "OKP", + "crv": "X25519", + "x": "SQ_7useLAjGf66XAwQWuBuSv9PdD_wB4TJQ6w38nFwQ" + } + } + ], + "authentication": [ + "#key-1" + ], + "keyAgreement": [ + "#key-2" + ], + "service": [ + { + "id": "#didcomm", + "type": "DIDCommMessaging", + "serviceEndpoint": { + "accept": [ + "didcomm/v2" + ], + "routingKeys": [], + "uri": "http://alice-mediator.com/" + } + } + ] + }"##, + ) + .unwrap(); + doc + } + + async fn test_jwt_data() -> String { + pub fn prev_secrets_resolver() -> impl SecretsResolver { + let secret_id = "did:key:z6MkrQT3VKYGkbPaYuJeBv31gNgpmVtRWP5yTocLDBgPpayM#z6MkrQT3VKYGkbPaYuJeBv31gNgpmVtRWP5yTocLDBgPpayM"; + let secret_material: Jwk = serde_json::from_str( + r#"{ + "kty": "OKP", + "crv": "Ed25519", + "x": "sZPvulKOXCES3D8Eya3LVnlgOpEaBohCqZ7emD8VXAA", + "d": "kUKFMD3RCZpk556fG0hx9GUrmdvb8t7k3TktPXCi4CY" + }"#, + ) + .unwrap(); + + let secret = Secrets { + id: None, + kid: secret_id.into(), + secret_material, + }; + + let keystore = MockKeyStore::new(vec![secret]); + LocalSecretsResolver::new(Arc::new(keystore)) + } + + let from_prior = FromPrior { + iss: prev_did(), + sub: new_did(), + aud: None, + exp: None, + nbf: None, + iat: None, + jti: None, + }; + + let did_resolver = LocalDIDResolver::new(&didoc()); + let kid = "did:key:z6MkrQT3VKYGkbPaYuJeBv31gNgpmVtRWP5yTocLDBgPpayM#z6MkrQT3VKYGkbPaYuJeBv31gNgpmVtRWP5yTocLDBgPpayM"; + let (jwt, _kid) = from_prior + .pack(Some(&kid), &did_resolver, &prev_secrets_resolver()) + .await + .unwrap(); + jwt + } + + fn test_message_payload(jwt: String) -> Message { + let msg = Message::build( + Uuid::new_v4().to_string(), + "https://didcomm.org/coordinate-mediation/2.0/keylist-update".to_owned(), + json!({"updates": [ + { + "recipient_did": "did:key:z6MkfyTREjTxQ8hUwSwBPeDHf3uPL3qCjSSuNPwsyMpWUGH7", + "action": "add" + }, + { + "recipient_did": "did:key:alice_identity_pub2@alice_mediator", + "action": "remove" + } + ]}), + ) + .header("return_route".into(), json!("all")) + .to("did:peer:2.Vz6Mkf6r1uMJwoRAbzkuyj2RwPusdZhWSPeEknnTcKv2C2EN7.Ez6LSgbP4b3y8HVWG6C73WF2zLbzjDAPXjc33P2VfnVVHE347.SeyJpZCI6IiNkaWRjb21tIiwicyI6eyJhIjpbImRpZGNvbW0vdjIiXSwiciI6W10sInVyaSI6Imh0dHA6Ly9hbGljZS1tZWRpYXRvci5jb20ifSwidCI6ImRtIn0".to_string()) + .from(new_did()) + .from_prior(jwt) + .finalize(); + msg + } + + #[tokio::test] + async fn unit_test_on_did_rotation() { + let jwt = test_jwt_data().await; + let state = setup(); + let AppStateRepository { + connection_repository, + .. + } = state.repository.as_ref().unwrap(); + + let msg = test_message_payload(jwt); + did_rotation(msg, &connection_repository).await.unwrap(); + + // assert if did was rotated on mediator's site + let _ = match connection_repository + .find_one_by(doc! {"client_did": new_did()}) + .await + .unwrap() + { + Some(conn) => { + assert_eq!(conn.client_did, new_did()) + } + None => { + panic!("Rotation Error") + } + }; + } +} diff --git a/crates/web-plugins/didcomm-messaging/src/did_rotation/mod.rs b/crates/web-plugins/didcomm-messaging/src/did_rotation/mod.rs index a56b4c1b..0a8efbaa 100644 --- a/crates/web-plugins/didcomm-messaging/src/did_rotation/mod.rs +++ b/crates/web-plugins/didcomm-messaging/src/did_rotation/mod.rs @@ -28,7 +28,7 @@ pub async fn did_rotation( let prev = from_prior.iss; // validate if did is known - let _ = match connection_repos + match connection_repos .find_one_by(doc! {"client_did": &prev}) .await .unwrap() @@ -47,8 +47,8 @@ pub async fn did_rotation( let did_index = connection.keylist.iter().position(|did| did == &prev); - if did_index.is_some() { - connection.keylist.swap_remove(did_index.unwrap()); + if let Some(did_index) = did_index { + connection.keylist.swap_remove(did_index); connection.keylist.push(new.clone()); } else { From bf109360dd379b4346cfe535de66015c4b8600c0 Mon Sep 17 00:00:00 2001 From: Hermann Core Date: Thu, 12 Dec 2024 09:08:55 +0100 Subject: [PATCH 4/7] fix clippy check --- crates/web-plugins/didcomm-messaging/did-utils/src/vc/model.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/web-plugins/didcomm-messaging/did-utils/src/vc/model.rs b/crates/web-plugins/didcomm-messaging/did-utils/src/vc/model.rs index b81eaad5..7ed20001 100644 --- a/crates/web-plugins/didcomm-messaging/did-utils/src/vc/model.rs +++ b/crates/web-plugins/didcomm-messaging/did-utils/src/vc/model.rs @@ -85,7 +85,7 @@ pub struct VerifiableCredential { /// The issuers of the credential. pub enum Issuers { Single(Box), - SetOf(Box>), + SetOf(Vec), } #[derive(Serialize, Debug, Clone, PartialEq, Deserialize)] From c4996cc69a767fc2354966097ed8269a2bfa051b Mon Sep 17 00:00:00 2001 From: Hermann Core Date: Thu, 12 Dec 2024 09:37:41 +0100 Subject: [PATCH 5/7] remove unused dependencies across the codebase --- crates/web-plugins/didcomm-messaging/Cargo.toml | 2 -- .../didcomm-messaging/message-api/Cargo.toml | 13 ------------- .../protocols/basic-message/Cargo.toml | 12 ------------ .../didcomm-messaging/protocols/forward/Cargo.toml | 1 - .../protocols/mediator-coordination/Cargo.toml | 4 ---- .../didcomm-messaging/protocols/pickup/Cargo.toml | 4 ---- .../protocols/trust-ping/Cargo.toml | 2 -- .../web-plugins/didcomm-messaging/shared/Cargo.toml | 4 ---- 8 files changed, 42 deletions(-) diff --git a/crates/web-plugins/didcomm-messaging/Cargo.toml b/crates/web-plugins/didcomm-messaging/Cargo.toml index e0a87c7c..fbb75aed 100644 --- a/crates/web-plugins/didcomm-messaging/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/Cargo.toml @@ -29,7 +29,6 @@ thiserror.workspace = true tokio = { workspace = true, features = ["full"] } hyper = { workspace = true, features = ["full"] } axum = { workspace = true, features = ["macros"] } -serde = { version = "1.0", features = ["derive"] } [features] @@ -50,7 +49,6 @@ mediator-coordination = ["dep:mediator-coordination"] [dev-dependencies] async-trait.workspace = true -mockall = "0.13.0" uuid = { workspace = true, features = ["v4"] } json-canon = "0.1.3" shared = { workspace = true, features = ["test-utils"] } diff --git a/crates/web-plugins/didcomm-messaging/message-api/Cargo.toml b/crates/web-plugins/didcomm-messaging/message-api/Cargo.toml index 8bef94c7..571b5c84 100644 --- a/crates/web-plugins/didcomm-messaging/message-api/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/message-api/Cargo.toml @@ -4,24 +4,11 @@ version = "0.1.0" edition = "2021" [dependencies] -keystore.workspace = true shared.workspace = true -database.workspace = true -filesystem.workspace = true async-trait.workspace = true -mongodb.workspace = true -anyhow.workspace = true -tracing.workspace = true -serde_json.workspace = true -thiserror.workspace = true didcomm = { workspace = true, features = ["uniffi"] } -hyper = { workspace = true, features = ["full"] } axum = { workspace = true, features = ["macros"] } [dev-dependencies] -keystore = { workspace = true, features = ["test-utils"] } shared = { workspace = true, features = ["test-utils"] } -did-utils.workspace = true -uuid = { workspace = true, features = ["v4"] } -tokio = { version = "1.27.0", default-features = false, features = ["macros", "rt"] } diff --git a/crates/web-plugins/didcomm-messaging/protocols/basic-message/Cargo.toml b/crates/web-plugins/didcomm-messaging/protocols/basic-message/Cargo.toml index 64ac8bae..58bb2e5b 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/basic-message/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/protocols/basic-message/Cargo.toml @@ -6,25 +6,13 @@ edition = "2021" [dependencies] shared.workspace = true did-utils.workspace = true -database.workspace = true keystore.workspace = true - -serde.workspace = true didcomm.workspace = true -mongodb.workspace = true serde_json.workspace = true -thiserror.workspace = true -uuid = { workspace = true, features = ["v4"] } axum = { workspace = true, features = ["macros"] } -tokio = { workspace = true, features = ["full"] } chrono.workspace = true [dev-dependencies] did-utils.workspace = true keystore.workspace = true -hyper = "0.14.27" shared = { workspace = true, features = ["test-utils"] } -tokio = { version = "1.27.0", default-features = false, features = [ - "macros", - "rt", -] } diff --git a/crates/web-plugins/didcomm-messaging/protocols/forward/Cargo.toml b/crates/web-plugins/didcomm-messaging/protocols/forward/Cargo.toml index 85278439..f48b31bb 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/forward/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/protocols/forward/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" keystore.workspace = true shared.workspace = true database.workspace = true -filesystem.workspace = true message-api.workspace = true mongodb.workspace = true diff --git a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/Cargo.toml b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/Cargo.toml index e8e55900..06dbca29 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/Cargo.toml @@ -6,9 +6,7 @@ edition = "2021" [dependencies] shared.workspace = true did-utils.workspace = true -database.workspace = true keystore.workspace = true -filesystem.workspace = true message-api.workspace = true mongodb.workspace = true @@ -19,7 +17,6 @@ async-trait.workspace = true serde_json.workspace = true thiserror.workspace = true tracing.workspace = true -cfg-if.workspace = true json-canon.workspace = true didcomm = { workspace = true, features = ["uniffi"] } tokio = { workspace = true, features = ["full"] } @@ -34,7 +31,6 @@ tokio = { version = "1.27.0", default-features = false, features = [ "macros", "rt", ] } -tower = { version = "0.4.13", features = ["util"] } shared = { workspace = true, features = ["test-utils"] } [features] diff --git a/crates/web-plugins/didcomm-messaging/protocols/pickup/Cargo.toml b/crates/web-plugins/didcomm-messaging/protocols/pickup/Cargo.toml index 97694183..96521436 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/pickup/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/protocols/pickup/Cargo.toml @@ -5,10 +5,7 @@ edition = "2021" [dependencies] shared.workspace = true -filesystem.workspace = true message-api.workspace = true -keystore.workspace = true -database.workspace = true serde.workspace = true didcomm.workspace = true @@ -20,7 +17,6 @@ uuid = { workspace = true, features = ["v4"] } axum = { workspace = true, features = ["macros"] } [dev-dependencies] -hyper = "0.14.27" shared = { workspace = true, features = ["test-utils"] } tokio = { version = "1.27.0", default-features = false, features = [ "macros", diff --git a/crates/web-plugins/didcomm-messaging/protocols/trust-ping/Cargo.toml b/crates/web-plugins/didcomm-messaging/protocols/trust-ping/Cargo.toml index 4a50e2d8..8dfe9f5f 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/trust-ping/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/protocols/trust-ping/Cargo.toml @@ -13,11 +13,9 @@ uuid.workspace = true async-trait.workspace = true serde_json.workspace = true thiserror.workspace = true -hyper = { workspace = true, features = ["full"] } axum = { workspace = true, features = ["macros"] } [dev-dependencies] -json-canon = "0.1.3" shared = { workspace = true, features = ["test-utils"] } tokio = { version = "1.27.0", default-features = false, features = [ "macros", diff --git a/crates/web-plugins/didcomm-messaging/shared/Cargo.toml b/crates/web-plugins/didcomm-messaging/shared/Cargo.toml index b9ad2128..6fa47937 100644 --- a/crates/web-plugins/didcomm-messaging/shared/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/shared/Cargo.toml @@ -15,15 +15,11 @@ serde.workspace = true serde_json.workspace = true async-trait.workspace = true mongodb.workspace = true -tracing.workspace = true eyre.workspace = true -hyper = { workspace = true, features = ["full"] } tokio = { workspace = true, features = ["full"] } -axum = { workspace = true, features = ["macros"] } didcomm = { workspace = true, features = ["uniffi"] } [dev-dependencies] -hyper = "0.14.27" tokio = { version = "1.27.0", default-features = false, features = [ "macros", "rt", From 03d24ca5fb002aab36946cbd767245bf32e0e211 Mon Sep 17 00:00:00 2001 From: Hermann Core Date: Tue, 17 Dec 2024 11:40:20 +0100 Subject: [PATCH 6/7] upgrade all dependencies to their latest versions --- Cargo.toml | 75 ++++++++++--------- crates/database/src/lib.rs | 15 ++-- crates/filesystem/Cargo.toml | 2 +- crates/filesystem/src/lib.rs | 9 +-- crates/web-plugins/did-endpoint/Cargo.toml | 5 +- crates/web-plugins/did-endpoint/src/web.rs | 5 +- .../web-plugins/didcomm-messaging/Cargo.toml | 5 +- .../didcomm-messaging/did-utils/Cargo.toml | 13 ++-- .../did-utils/src/methods/errors.rs | 2 + .../did-utils/src/methods/web/resolver.rs | 42 ++++++----- .../protocols/forward/Cargo.toml | 2 +- .../mediator-coordination/Cargo.toml | 4 +- .../protocols/pickup/Cargo.toml | 2 +- .../protocols/trust-ping/Cargo.toml | 2 +- .../didcomm-messaging/shared/Cargo.toml | 2 +- .../didcomm-messaging/src/error.rs | 9 +-- .../didcomm-messaging/src/midlw.rs | 37 +++++---- .../didcomm-messaging/src/web/dispatcher.rs | 9 ++- crates/web-plugins/oob-messages/Cargo.toml | 6 +- crates/web-plugins/oob-messages/src/models.rs | 13 +++- src/main.rs | 24 +++--- src/plugins/index/web.rs | 5 +- 22 files changed, 155 insertions(+), 133 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2a33a6ac..6bb97444 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,50 +48,52 @@ mediator-coordination = { path = "./crates/web-plugins/didcomm-messaging/protoco # Other common dependencies serde = "1.0" sha2 = "0.10" -cfg-if = "0.1" +cfg-if = "1.0" getrandom = "0.2" -hyper-tls = "0.5.0" -json-patch = "1.0.0" -x25519-dalek = "2.0.0-rc.3" -multibase = "0.8.0" +hyper-tls = "0.6.0" +json-patch = "3.0.1" +x25519-dalek = "2.0.1" +multibase = "0.9.1" json-canon = "0.1.3" -qrcode = "0.12.0" -image = "0.23" -reqwest = "0.11" +qrcode = "0.14.1" +image = "0.25" +reqwest = "0.12" tempdir = "0.3.7" -headers = "0.3" -thiserror = "1.0.48" -url = "2.4.1" -num-bigint = "0.4.4" -base64 = "0.13.0" +headers = "0.4" +thiserror = "2.0.7" +url = "2.5.4" +num-bigint = "0.4.6" +base64 = "0.22.1" hex = "0.4.3" eyre = "0.6" anyhow = "1" -subtle = "2.5.0" -regex = "1.10.2" -mongodb = "2.7.1" -once_cell = "1.20.0" -tower = "0.4" -nix = "0.22.0" -uuid = "1.4.1" -axum = "0.6.20" -tokio = "1.30.0" -tracing = "0.1.37" -chrono = "0.4.26" -paste = "0.1" +subtle = "2.6.1" +regex = "1.11.1" +mongodb = "3.1.1" +once_cell = "1.20.2" +tower = "0.5" +nix = "0.29.0" +uuid = "1.11.0" +axum = "0.7.9" +tokio = "1.42.0" +tracing = "0.1.41" +chrono = "0.4.39" +paste = "1.0" didcomm = "0.4.1" -hyper = "0.14.27" -lazy_static = "1.4.0" -async-trait = "0.1.73" -dotenv-flow = "0.15.0" +hyper = "1.5.2" +hyper-util = "0.1" +http-body-util = "0.1" +lazy_static = "1.5.0" +async-trait = "0.1.83" +dotenv-flow = "0.16.2" serde_json = "1.0" -parking_lot = "0.12.0" -curve25519-dalek = "4.0.0-rc.3" -ed25519-dalek = "2.0.0-rc.3" -tracing-subscriber = "0.3.17" -tower-http = "0.4.3" +parking_lot = "0.12.3" +curve25519-dalek = "4.1.3" +ed25519-dalek = "2.1.1" +tracing-subscriber = "0.3.19" +tower-http = "0.6.2" base64ct = { version = "1.6.0", default-features = false } -zeroize = { version = "1.6.0", default-features = false } +zeroize = { version = "1.8.1", default-features = false } [dependencies] @@ -105,6 +107,7 @@ tracing.workspace = true lazy_static.workspace = true serde_json.workspace = true hyper.workspace = true +http-body-util.workspace = true tokio = { workspace = true, features = ["full"] } tracing-subscriber = { workspace = true, features = ["json"] } tower-http = { workspace = true, features = ["catch-panic", "trace", "cors"] } @@ -136,4 +139,4 @@ mediator-coordination = ["plugin-didcomm_messaging", "didcomm-messaging/mediator [dev-dependencies] -tower = { version = "0.4.13", features = ["util"] } +tower = { version = "0.5.2", features = ["util"] } diff --git a/crates/database/src/lib.rs b/crates/database/src/lib.rs index 079f558a..cb25bb46 100644 --- a/crates/database/src/lib.rs +++ b/crates/database/src/lib.rs @@ -77,7 +77,7 @@ where let collection = self.get_collection(); // Lock the Mutex and get the Collection - let mut cursor = collection.read().await.find(None, None).await?; + let mut cursor = collection.read().await.find(doc! {}).await?; while cursor.advance().await? { entities.push(cursor.deserialize_current()?); } @@ -91,7 +91,7 @@ where // Lock the Mutex and get the Collection let collection = collection.read().await; Ok(collection - .count_documents(filter, None) + .count_documents(filter) .await? .try_into() .map_err(|_| RepositoryError::Generic("count overflow".to_owned()))?) @@ -108,7 +108,7 @@ where // Lock the Mutex and get the Collection let collection = collection.read().await; - Ok(collection.find_one(filter, None).await?) + Ok(collection.find_one(filter).await?) } /// Stores a new entity. @@ -119,7 +119,7 @@ where let collection = collection.read().await; // Insert the new entity into the database - let metadata = collection.insert_one(entity.clone(), None).await?; + let metadata = collection.insert_one(entity.clone()).await?; // Set the ID if it was inserted and return the updated entity if let Bson::ObjectId(oid) = metadata.inserted_id { @@ -144,7 +144,7 @@ where let collection = collection.read().await; // Retrieve all entities from the database - let mut cursor = collection.find(filter, find_options).await?; + let mut cursor = collection.find(filter).with_options(find_options).await?; while cursor.advance().await? { entities.push(cursor.deserialize_current()?); } @@ -160,7 +160,7 @@ where let collection = collection.read().await; // Delete the entity from the database - collection.delete_one(doc! {"_id": id}, None).await?; + collection.delete_one(doc! {"_id": id}).await?; Ok(()) } @@ -179,8 +179,7 @@ where let metadata = collection .update_one( doc! {"_id": entity.id().unwrap()}, - doc! {"$set": bson::to_document(&entity).map_err(|_| RepositoryError::BsonConversionError)?}, - None, + doc! {"$set": bson::to_document(&entity).map_err(|_| RepositoryError::BsonConversionError)?} ) .await?; diff --git a/crates/filesystem/Cargo.toml b/crates/filesystem/Cargo.toml index e9b11a00..4db32f60 100644 --- a/crates/filesystem/Cargo.toml +++ b/crates/filesystem/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -nix.workspace = true +nix ={ workspace = true, features = ["fs"] } [features] test-utils = [] diff --git a/crates/filesystem/src/lib.rs b/crates/filesystem/src/lib.rs index 301bc195..ddc4066d 100644 --- a/crates/filesystem/src/lib.rs +++ b/crates/filesystem/src/lib.rs @@ -1,14 +1,13 @@ -use nix::fcntl::{flock, FlockArg}; +use nix::fcntl::{Flock, FlockArg}; use std::{ fs::OpenOptions, io::{Error as IoError, ErrorKind, Result as IoResult}, - os::unix::io::AsRawFd, path::Path, }; #[doc(hidden)] // Define a trait for file system operations -pub trait FileSystem: Send + Sync + 'static { +pub trait FileSystem: Send + 'static { fn read_to_string(&self, path: &Path) -> IoResult; fn write(&mut self, path: &Path, content: &str) -> IoResult<()>; fn read_dir_files(&self, path: &Path) -> IoResult>; @@ -59,7 +58,7 @@ impl FileSystem for StdFileSystem { .open(path)?; // Acquire an exclusive lock before writing to the file - flock(file.as_raw_fd(), FlockArg::LockExclusive) + let file = Flock::lock(file, FlockArg::LockExclusive) .map_err(|_| IoError::new(ErrorKind::Other, "Error acquiring file lock"))?; std::fs::write(path, content).map_err(|_| { @@ -70,7 +69,7 @@ impl FileSystem for StdFileSystem { })?; // Release the lock after writing to the file - flock(file.as_raw_fd(), FlockArg::Unlock) + file.unlock() .map_err(|_| IoError::new(ErrorKind::Other, "Error releasing file lock"))?; Ok(()) diff --git a/crates/web-plugins/did-endpoint/Cargo.toml b/crates/web-plugins/did-endpoint/Cargo.toml index c3b6f25f..5d649156 100644 --- a/crates/web-plugins/did-endpoint/Cargo.toml +++ b/crates/web-plugins/did-endpoint/Cargo.toml @@ -18,6 +18,7 @@ serde_json.workspace = true dotenv-flow.workspace = true multibase.workspace = true tracing.workspace = true +http-body-util.workspace = true uuid = { workspace = true, features = ["v4"] } hyper = { workspace = true, features = ["full"] } tokio = { workspace = true, features = ["full"] } @@ -25,8 +26,8 @@ axum = { workspace = true, features = ["macros"] } [dev-dependencies] async-trait.workspace = true -mockall = "0.13.0" +mockall = "0.13.1" json-canon = "0.1.3" filesystem = { workspace = true, features = ["test-utils"] } keystore = { workspace = true, features = ["test-utils"] } -tower = { version = "0.4.13", features = ["util"] } +tower = { version = "0.5.2", features = ["util"] } diff --git a/crates/web-plugins/did-endpoint/src/web.rs b/crates/web-plugins/did-endpoint/src/web.rs index 2e1e622b..11e59900 100644 --- a/crates/web-plugins/did-endpoint/src/web.rs +++ b/crates/web-plugins/did-endpoint/src/web.rs @@ -199,6 +199,7 @@ mod tests { proof::{CryptoProof, EdDsaJcs2022}, vc::VerifiablePresentation, }; + use http_body_util::BodyExt; use serde_json::json; use tower::util::ServiceExt; @@ -284,8 +285,8 @@ mod tests { assert_eq!(response.status(), StatusCode::OK); - let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); - let vp: VerifiablePresentation = serde_json::from_slice(&body).unwrap(); + let body = BodyExt::collect(response.into_body()).await.unwrap(); + let vp: VerifiablePresentation = serde_json::from_slice(&body.to_bytes()).unwrap(); let vc = vp.verifiable_credential.get(0).unwrap(); let diddoc = serde_json::from_value(json!(vc.credential_subject)).unwrap(); diff --git a/crates/web-plugins/didcomm-messaging/Cargo.toml b/crates/web-plugins/didcomm-messaging/Cargo.toml index fbb75aed..33261701 100644 --- a/crates/web-plugins/didcomm-messaging/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/Cargo.toml @@ -26,6 +26,7 @@ tracing.workspace = true once_cell.workspace = true serde_json.workspace = true thiserror.workspace = true +http-body-util.workspace = true tokio = { workspace = true, features = ["full"] } hyper = { workspace = true, features = ["full"] } axum = { workspace = true, features = ["macros"] } @@ -52,8 +53,8 @@ async-trait.workspace = true uuid = { workspace = true, features = ["v4"] } json-canon = "0.1.3" shared = { workspace = true, features = ["test-utils"] } -tokio = { version = "1.27.0", default-features = false, features = [ +tokio = { version = "1.42.0", default-features = false, features = [ "macros", "rt", ] } -tower = { version = "0.4.13", features = ["util"] } +tower = { version = "0.5.2", features = ["util"] } diff --git a/crates/web-plugins/didcomm-messaging/did-utils/Cargo.toml b/crates/web-plugins/didcomm-messaging/did-utils/Cargo.toml index 99afeed9..ed70e067 100644 --- a/crates/web-plugins/didcomm-messaging/did-utils/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/did-utils/Cargo.toml @@ -5,11 +5,14 @@ edition = "2021" [dependencies] serde_json.workspace = true -chrono = { workspace = true, features = ["serde"] } -hyper = { workspace = true, features = ["client", "http2"] } tokio.workspace = true serde.workspace = true +axum.workspace = true hyper-tls.workspace = true +http-body-util.workspace = true +hyper-util ={ workspace = true, features = ["full"] } +hyper = { workspace = true, features = ["full"] } +chrono = { workspace = true, features = ["serde"] } # Cross-platform random number generator from os getrandom = { workspace = true, features = ["js"] } @@ -38,10 +41,10 @@ subtle.workspace = true regex.workspace = true [dev-dependencies] -hyper = { version = "0.14.26", features = ["server"] } -async-std = { version = "1.12.0", features = ["attributes"] } +hyper = { version = "1.5.2", features = ["server"] } +async-std = { version = "1.13.0", features = ["attributes"] } hex = "0.4.3" -tokio = { version = "1.27.0", default-features = false, features = [ +tokio = { version = "1.42.0", default-features = false, features = [ "macros", "rt", ] } diff --git a/crates/web-plugins/didcomm-messaging/did-utils/src/methods/errors.rs b/crates/web-plugins/didcomm-messaging/did-utils/src/methods/errors.rs index daba60b6..20e74a72 100644 --- a/crates/web-plugins/didcomm-messaging/did-utils/src/methods/errors.rs +++ b/crates/web-plugins/didcomm-messaging/did-utils/src/methods/errors.rs @@ -66,6 +66,8 @@ pub enum DidWebError { #[error("Parsing error: {0}")] ParsingError(#[from] ParsingErrorSource), #[error("URL parsing error: {0}")] + HttpClientError(#[from] hyper_util::client::legacy::Error), + #[error("URL parsing error: {0}")] HttpError(#[from] hyper::Error), #[error("Non-success server response: {0}")] NonSuccessResponse(StatusCode), diff --git a/crates/web-plugins/didcomm-messaging/did-utils/src/methods/web/resolver.rs b/crates/web-plugins/didcomm-messaging/did-utils/src/methods/web/resolver.rs index c33fe21d..8a9dfd3c 100644 --- a/crates/web-plugins/didcomm-messaging/did-utils/src/methods/web/resolver.rs +++ b/crates/web-plugins/didcomm-messaging/did-utils/src/methods/web/resolver.rs @@ -1,11 +1,19 @@ use crate::methods::resolution::{DIDResolutionMetadata, DIDResolutionOptions, MediaType, ResolutionOutput}; use async_trait::async_trait; +use http_body_util::{BodyExt, Full}; use hyper::{ - client::{connect::Connect, HttpConnector}, + body::Bytes, http::uri::{self, Scheme}, - Body, Client, Uri, + Uri, }; use hyper_tls::HttpsConnector; +use hyper_util::{ + client::legacy::{ + connect::{Connect, HttpConnector}, + Client, + }, + rt::TokioExecutor, +}; use crate::ldmodel::Context; use crate::methods::{errors::DidWebError, traits::DIDResolver}; @@ -17,7 +25,7 @@ pub struct DidWeb where C: Connect + Send + Sync + Clone + 'static, { - client: Client, + client: Client>, } impl DidWeb { @@ -25,7 +33,7 @@ impl DidWeb { #[cfg(test)] pub fn http() -> DidWeb { DidWeb { - client: Client::builder().build::<_, Body>(HttpConnector::new()), + client: Client::builder(TokioExecutor::new()).build_http(), } } } @@ -40,7 +48,7 @@ impl DidWeb> { /// Creates a new `DidWeb` resolver. pub fn new() -> DidWeb> { DidWeb { - client: Client::builder().build::<_, Body>(HttpsConnector::new()), + client: Client::builder(TokioExecutor::new()).build::<_, Full>(HttpsConnector::new()), } } } @@ -57,9 +65,9 @@ where return Err(DidWebError::NonSuccessResponse(res.status())); } - let body = hyper::body::to_bytes(res.into_body()).await?; + let body = BodyExt::collect(res.into_body()).await?; - String::from_utf8(body.to_vec()).map_err(|err| err.into()) + String::from_utf8(body.to_bytes().to_vec()).map_err(|err| err.into()) } /// Fetches and parses a DID document for the given DID. @@ -158,16 +166,12 @@ where mod tests { use super::*; - use hyper::{ - service::{make_service_fn, service_fn}, - Body, Request, Response, Server, - }; - + use axum::{body::Body, extract::Request, response::Response, routing::get}; use serde_json::Value; - use std::convert::Infallible; - use std::net::SocketAddr; + use std::{convert::Infallible, net::SocketAddr}; + use tokio::net::TcpListener; - async fn mock_server_handler(req: Request) -> Result, Infallible> { + async fn mock_server_handler(req: Request) -> Result { const DID_JSON: &str = r#" {"@context": "https://www.w3.org/ns/did/v1", "id": "did:web:localhost", @@ -194,13 +198,13 @@ mod tests { } async fn create_mock_server(port: u16) -> String { - let make_svc = make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(mock_server_handler)) }); - let addr = SocketAddr::from(([127, 0, 0, 1], port)); - let server = Server::bind(&addr).serve(make_svc); + let listener = TcpListener::bind(addr).await.unwrap(); + + let app = axum::Router::new().route("/.well-known/did.json", get(mock_server_handler)); tokio::spawn(async move { - server.await.unwrap(); + axum::serve(listener, app).await.unwrap(); }); "localhost".to_string() diff --git a/crates/web-plugins/didcomm-messaging/protocols/forward/Cargo.toml b/crates/web-plugins/didcomm-messaging/protocols/forward/Cargo.toml index f48b31bb..e38d2ee0 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/forward/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/protocols/forward/Cargo.toml @@ -22,4 +22,4 @@ keystore = { workspace = true, features = ["test-utils"] } shared = { workspace = true, features = ["test-utils"] } did-utils.workspace = true uuid = { workspace = true, features = ["v4"] } -tokio = { version = "1.27.0", default-features = false, features = ["macros", "rt"] } +tokio = { version = "1.42.0", default-features = false, features = ["macros", "rt"] } diff --git a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/Cargo.toml b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/Cargo.toml index 06dbca29..ae2f366d 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/protocols/mediator-coordination/Cargo.toml @@ -25,9 +25,9 @@ uuid = { workspace = true, features = ["v4"] } hyper = { workspace = true, features = ["full"] } [dev-dependencies] -hyper = "0.14.27" +hyper = "1.5.2" json-canon = "0.1.3" -tokio = { version = "1.27.0", default-features = false, features = [ +tokio = { version = "1.42.0", default-features = false, features = [ "macros", "rt", ] } diff --git a/crates/web-plugins/didcomm-messaging/protocols/pickup/Cargo.toml b/crates/web-plugins/didcomm-messaging/protocols/pickup/Cargo.toml index 96521436..9ef52784 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/pickup/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/protocols/pickup/Cargo.toml @@ -18,7 +18,7 @@ axum = { workspace = true, features = ["macros"] } [dev-dependencies] shared = { workspace = true, features = ["test-utils"] } -tokio = { version = "1.27.0", default-features = false, features = [ +tokio = { version = "1.42.0", default-features = false, features = [ "macros", "rt", ] } diff --git a/crates/web-plugins/didcomm-messaging/protocols/trust-ping/Cargo.toml b/crates/web-plugins/didcomm-messaging/protocols/trust-ping/Cargo.toml index 8dfe9f5f..1648d9d4 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/trust-ping/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/protocols/trust-ping/Cargo.toml @@ -17,7 +17,7 @@ axum = { workspace = true, features = ["macros"] } [dev-dependencies] shared = { workspace = true, features = ["test-utils"] } -tokio = { version = "1.27.0", default-features = false, features = [ +tokio = { version = "1.42.0", default-features = false, features = [ "macros", "rt", ] } diff --git a/crates/web-plugins/didcomm-messaging/shared/Cargo.toml b/crates/web-plugins/didcomm-messaging/shared/Cargo.toml index 6fa47937..3509ec95 100644 --- a/crates/web-plugins/didcomm-messaging/shared/Cargo.toml +++ b/crates/web-plugins/didcomm-messaging/shared/Cargo.toml @@ -20,7 +20,7 @@ tokio = { workspace = true, features = ["full"] } didcomm = { workspace = true, features = ["uniffi"] } [dev-dependencies] -tokio = { version = "1.27.0", default-features = false, features = [ +tokio = { version = "1.42.0", default-features = false, features = [ "macros", "rt", ] } diff --git a/crates/web-plugins/didcomm-messaging/src/error.rs b/crates/web-plugins/didcomm-messaging/src/error.rs index a4eeec02..de3a9a87 100644 --- a/crates/web-plugins/didcomm-messaging/src/error.rs +++ b/crates/web-plugins/didcomm-messaging/src/error.rs @@ -1,5 +1,4 @@ use axum::Json; -use didcomm::error::ErrorKind as DidcommErrorKind; use serde_json::{json, Value}; use thiserror::Error; @@ -10,14 +9,10 @@ pub(crate) enum Error { AnonymousPacker, #[error("assumed didcomm-encrypted message is malformed")] MalformedDidcommEncrypted, - #[error("could not unpack message")] - MessageUnpackingFailure, - #[error("could not pack message: {0}")] - MessagePackingFailure(DidcommErrorKind), + #[error("Internal server error")] + InternalServer, #[error("unsupported content-type, only accept application/didcomm-encrypted+json")] NotDidcommEncryptedPayload, - #[error("unparseable payload")] - UnparseablePayload, } impl Error { diff --git a/crates/web-plugins/didcomm-messaging/src/midlw.rs b/crates/web-plugins/didcomm-messaging/src/midlw.rs index 19774e54..bb2549c4 100644 --- a/crates/web-plugins/didcomm-messaging/src/midlw.rs +++ b/crates/web-plugins/didcomm-messaging/src/midlw.rs @@ -1,11 +1,13 @@ use axum::{ body::Body, extract::State, - http::{header, Request, StatusCode}, + http::{header, StatusCode}, middleware::Next, response::{IntoResponse, Response}, }; -use didcomm::{error::ErrorKind as DidcommErrorKind, Message, PackEncryptedOptions, UnpackOptions}; +use didcomm::{Message, PackEncryptedOptions, UnpackOptions}; +use http_body_util::BodyExt; +use hyper::Request; use serde_json::Value; use std::sync::Arc; @@ -24,7 +26,7 @@ use shared::{ pub async fn unpack_didcomm_message( State(state): State>, request: Request, - next: Next, + next: Next, ) -> Response { // Enforce request content type to match `didcomm-encrypted+json` let content_type = request @@ -38,15 +40,17 @@ pub async fn unpack_didcomm_message( // Extract request payload let (parts, body) = request.into_parts(); - let bytes = match hyper::body::to_bytes(body).await { - Ok(bytes) => bytes, + let collected = match BodyExt::collect(body).await { + Ok(collected) => collected, Err(_) => { - let response = (StatusCode::BAD_REQUEST, Error::UnparseablePayload.json()); + tracing::error!("Failed to parse request body"); + let response = (StatusCode::BAD_REQUEST, Error::InternalServer.json()); return response.into_response(); } }; + let bytes = collected.to_bytes(); let payload = String::from_utf8_lossy(&bytes); // Attempt to unpack request payload @@ -114,10 +118,11 @@ async fn unpack_payload( ) .await; - let (plain_message, metadata) = res.map_err(|_| { + let (plain_message, metadata) = res.map_err(|err| { + tracing::error!("Failed to unpack message: {err:?}"); let response = ( - StatusCode::BAD_REQUEST, - Error::MessageUnpackingFailure.json(), + StatusCode::INTERNAL_SERVER_ERROR, + Error::InternalServer.json(), ); response.into_response() @@ -151,9 +156,10 @@ pub async fn pack_response_message( let to = msg.to.as_ref().and_then(|v| v.first()); if from.is_none() || to.is_none() { + tracing::error!("Failed to pack message: missing from or to field"); let response = ( StatusCode::INTERNAL_SERVER_ERROR, - Error::MessagePackingFailure(DidcommErrorKind::Malformed).json(), + Error::InternalServer.json(), ); return Err(response.into_response()); @@ -170,9 +176,10 @@ pub async fn pack_response_message( .await .map(|(packed_message, _metadata)| serde_json::from_str(&packed_message).unwrap()) .map_err(|err| { + tracing::error!("Failed to pack message: {err:?}"); let response = ( StatusCode::INTERNAL_SERVER_ERROR, - Error::MessagePackingFailure(err.kind()).json(), + Error::InternalServer.json(), ); response.into_response() @@ -236,7 +243,7 @@ mod tests { .await .unwrap_err(), StatusCode::INTERNAL_SERVER_ERROR, - Error::MessagePackingFailure(DidcommErrorKind::Malformed), + Error::InternalServer, ) .await; } @@ -262,7 +269,7 @@ mod tests { .await .unwrap_err(), StatusCode::INTERNAL_SERVER_ERROR, - Error::MessagePackingFailure(DidcommErrorKind::Unsupported), + Error::InternalServer, ) .await; } @@ -274,8 +281,8 @@ mod tests { async fn _assert_midlw_err(err: Response, status: StatusCode, mediation_error: Error) { assert_eq!(err.status(), status); - let body = hyper::body::to_bytes(err.into_body()).await.unwrap(); - let body: Value = serde_json::from_slice(&body).unwrap(); + let body = BodyExt::collect(err.into_body()).await.unwrap(); + let body: Value = serde_json::from_slice(&body.to_bytes()).unwrap(); assert_eq!( json_canon::to_string(&body).unwrap(), diff --git a/crates/web-plugins/didcomm-messaging/src/web/dispatcher.rs b/crates/web-plugins/didcomm-messaging/src/web/dispatcher.rs index 42ba828f..347bf6ed 100644 --- a/crates/web-plugins/didcomm-messaging/src/web/dispatcher.rs +++ b/crates/web-plugins/didcomm-messaging/src/web/dispatcher.rs @@ -62,7 +62,8 @@ mod tests { use super::*; use crate::manager::MessagePluginContainer; use axum::Router; - use hyper::{Body, Method, Request}; + use http_body_util::{BodyExt, Full}; + use hyper::{body::Bytes, Method, Request}; use message_api::{MessageHandler, MessagePlugin, MessageRouter}; use once_cell::sync::Lazy; use serde_json::{json, Value}; @@ -188,7 +189,7 @@ mod tests { .uri(String::from("/")) .method(Method::POST) .header(CONTENT_TYPE, DIDCOMM_ENCRYPTED_MIME_TYPE) - .body(Body::from(packed_msg)) + .body(Full::new(Bytes::from(packed_msg))) .unwrap(), ) .await @@ -202,8 +203,8 @@ mod tests { ); // Parse response's body - let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); - let body: Value = serde_json::from_slice(&body).unwrap(); + let body = BodyExt::collect(response.into_body()).await.unwrap(); + let body: Value = serde_json::from_slice(&body.to_bytes()).unwrap(); let response = serde_json::to_string(&body).unwrap(); // Decrypt response diff --git a/crates/web-plugins/oob-messages/Cargo.toml b/crates/web-plugins/oob-messages/Cargo.toml index b6ebda1c..ca1ee437 100644 --- a/crates/web-plugins/oob-messages/Cargo.toml +++ b/crates/web-plugins/oob-messages/Cargo.toml @@ -21,6 +21,6 @@ uuid = { workspace = true, features = ["fast-rng", "v4"] } [dev-dependencies] filesystem = { workspace = true, features = ["test-utils"] } -mockall = "0.13.0" -tokio = { version = "1.30.0", features = ["full"] } -tower = "0.4" +mockall = "0.13.1" +tokio = { version = "1.42.0", features = ["full"] } +tower = "0.5" diff --git a/crates/web-plugins/oob-messages/src/models.rs b/crates/web-plugins/oob-messages/src/models.rs index b41415a9..1526c2c5 100644 --- a/crates/web-plugins/oob-messages/src/models.rs +++ b/crates/web-plugins/oob-messages/src/models.rs @@ -1,5 +1,6 @@ use crate::constants::OOB_INVITATION_2_0; -use base64::{encode_config, STANDARD}; +use base64::engine::general_purpose::STANDARD; +use base64::Engine; use did_utils::didcore::Document; use filesystem::FileSystem; use image::{DynamicImage, Luma}; @@ -9,6 +10,7 @@ use qrcode::QrCode; use serde::{Deserialize, Serialize}; use serde_json::to_string; use std::collections::HashMap; +use std::io::Cursor; use std::sync::RwLock; #[cfg(test)] @@ -163,13 +165,16 @@ where // Convert the image to a PNG-encoded byte vector let dynamic_image = DynamicImage::ImageLuma8(image); - let mut buffer = Vec::new(); + let mut buffer = Cursor::new(Vec::new()); dynamic_image - .write_to(&mut buffer, image::ImageOutputFormat::Png) + .write_to(&mut buffer, image::ImageFormat::Png) .map_err(|err| format!("Error encoding image to PNG: {err}"))?; + // Get the encoded bytes from the cursor + let buffer = buffer.into_inner(); + // Save the PNG-encoded byte vector as a base64-encoded string - let base64_string = encode_config(&buffer, STANDARD); + let base64_string = STANDARD.encode(&buffer); // Save to file fs.write_with_lock(path.as_ref(), &base64_string) diff --git a/src/main.rs b/src/main.rs index f9c0a739..adfb7f5f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ -use axum::Server; +use std::net::SocketAddr; use didcomm_mediator::app; use eyre::{Result, WrapErr}; -use std::net::SocketAddr; +use tokio::net::TcpListener; #[tokio::main] async fn main() -> Result<()> { @@ -11,15 +11,17 @@ async fn main() -> Result<()> { // Enable logging config_tracing(); - // Start server + // Configure server let port = std::env::var("SERVER_LOCAL_PORT").unwrap_or("3000".to_owned()); - let addr: SocketAddr = format!("0.0.0.0:{port}") - .parse() + let port = port.parse().context("failed to parse port")?; + let addr = SocketAddr::from(([0, 0, 0, 0], port)); + let listener = TcpListener::bind(addr) + .await .context("failed to parse address")?; - tracing::debug!("listening on {}", addr); + tracing::debug!("listening on {addr}"); - generic_server_with_graceful_shutdown(addr) + generic_server_with_graceful_shutdown(listener) .await .map_err(|err| { tracing::error!("{err:?}"); @@ -29,14 +31,12 @@ async fn main() -> Result<()> { Ok(()) } -async fn generic_server_with_graceful_shutdown(addr: SocketAddr) -> Result<()> { +async fn generic_server_with_graceful_shutdown(listener: TcpListener) -> Result<()> { // Load plugins let (mut plugin_container, router) = app()?; - // Spawn task for server - - Server::bind(&addr) - .serve(router.into_make_service()) + // Start server + axum::serve(listener, router) .await .context("failed to start server")?; diff --git a/src/plugins/index/web.rs b/src/plugins/index/web.rs index 32930b94..eef061e8 100644 --- a/src/plugins/index/web.rs +++ b/src/plugins/index/web.rs @@ -29,6 +29,7 @@ mod tests { }; use serde_json::Value; use tower::util::ServiceExt; + use http_body_util::BodyExt; #[tokio::test] async fn index() { @@ -46,8 +47,8 @@ mod tests { assert_eq!(response.status(), StatusCode::OK); - let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); - let body: Value = serde_json::from_slice(&body).unwrap(); + let body = BodyExt::collect(response.into_body()).await.unwrap(); + let body: Value = serde_json::from_slice(&body.to_bytes()).unwrap(); assert_eq!(body.get("app").unwrap(), &crate_name()); } From d742cf818de1c19048e6b2b2e2f4c159a3202b54 Mon Sep 17 00:00:00 2001 From: Hermann Core Date: Tue, 17 Dec 2024 11:46:10 +0100 Subject: [PATCH 7/7] fix formatting --- src/main.rs | 2 +- src/plugins/index/web.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index adfb7f5f..888e99c1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ -use std::net::SocketAddr; use didcomm_mediator::app; use eyre::{Result, WrapErr}; +use std::net::SocketAddr; use tokio::net::TcpListener; #[tokio::main] diff --git a/src/plugins/index/web.rs b/src/plugins/index/web.rs index eef061e8..e4a43943 100644 --- a/src/plugins/index/web.rs +++ b/src/plugins/index/web.rs @@ -27,9 +27,9 @@ mod tests { body::Body, http::{Request, StatusCode}, }; + use http_body_util::BodyExt; use serde_json::Value; use tower::util::ServiceExt; - use http_body_util::BodyExt; #[tokio::test] async fn index() {