From 9db22a857c6e16aee51c007c2884cc259b1483ce Mon Sep 17 00:00:00 2001 From: YoussefAWasfy Date: Thu, 26 Sep 2024 10:42:46 +0200 Subject: [PATCH 1/2] test: add unit tests for create did peer --- Cargo.lock | 5 + Cargo.toml | 2 +- .../did-peer/src/lib.rs | 284 ++++++++++++++++++ 3 files changed, 290 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index e7c9047..b762b39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4818,6 +4818,7 @@ dependencies = [ "k256", "keccak-hash", "p256", + "p384", "pin-project", "rand", "ripemd160", @@ -4916,6 +4917,7 @@ dependencies = [ "locspan", "multibase 0.9.1", "p256", + "p384", "pin-project", "rand", "rdf-types", @@ -5073,6 +5075,7 @@ dependencies = [ "num-derive", "num-traits", "p256", + "p384", "rand", "rsa", "serde", @@ -5101,6 +5104,7 @@ dependencies = [ "k256", "linked-data", "p256", + "p384", "rand", "rsa", "serde", @@ -5337,6 +5341,7 @@ dependencies = [ "linked-data", "multibase 0.9.1", "p256", + "p384", "pin-project", "rand_core", "rdf-types", diff --git a/Cargo.toml b/Cargo.toml index c87461b..f83b408 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ regex = "1" serde = { version = "1.0", features = ["derive", "rc"] } serde_json = "1.0" blake2 = "0.10" -ssi = "0.9" +ssi = { version = "0.9", features = ["secp384r1"] } thiserror = "1.0" tokio = { version = "1.40", features = ["full"] } tracing = "0.1" diff --git a/affinidi-did-resolver-methods/did-peer/src/lib.rs b/affinidi-did-resolver-methods/did-peer/src/lib.rs index 0adb53b..ad15be6 100644 --- a/affinidi-did-resolver-methods/did-peer/src/lib.rs +++ b/affinidi-did-resolver-methods/did-peer/src/lib.rs @@ -752,6 +752,290 @@ impl DIDPeer { } } +#[cfg(test)] +mod test { + use ssi::{dids::DIDBuf, JWK}; + + use crate::{ + DIDPeer, DIDPeerCreateKeys, DIDPeerKeyType, DIDPeerKeys, DIDPeerService, + PeerServiceEndPoint, PeerServiceEndPointLong, + }; + + #[tokio::test] + async fn create_peer_did_without_keys_and_services() { + let keys: Vec = vec![]; + let services: Vec = vec![]; + + let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap(); + let parts: Vec<&str> = did.split(":").collect(); + + assert_eq!(parts.len(), 3); + assert_eq!(parts[1], "peer"); + assert!(parts[2].len() == 1); + } + + #[tokio::test] + async fn create_peer_did_without_keys() { + let keys: Vec = vec![]; + let services = vec![DIDPeerService { + _type: "dm".into(), + service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong { + uri: "https://localhost:7037".into(), + accept: vec!["didcomm/v2".into()], + routing_keys: vec![], + }), + id: None, + }]; + + let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap(); + let parts: Vec<&str> = did.split(":").collect(); + let method_ids: Vec<&str> = parts[2].split(".").collect(); + + assert_eq!(parts.len(), 3); + assert_eq!(parts[1], "peer"); + assert!(method_ids.len() > 1); + assert!(method_ids[1].len() > 1); + } + + #[tokio::test] + async fn create_peer_did_without_services() { + let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::Ed25519), true); + let services: Vec = vec![]; + + let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap(); + let parts: Vec<&str> = did.split(":").collect(); + let mut method_ids: Vec<&str> = parts[2].split(".").collect(); + method_ids = method_ids[1..].to_vec(); + let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()]; + + for i in 0..2 { + assert!(keys_multibase.contains(&method_ids[i][1..].to_string())); + } + assert_eq!(parts.len(), 3); + assert_eq!(parts[1], "peer"); + } + + #[should_panic(expected = "UnsupportedKeyType")] + #[tokio::test] + async fn create_peer_did_should_throw_unsupported_key_error_p384() { + let (_, _, keys) = _get_keys(None, false); + // Create a service definition + let services = vec![DIDPeerService { + _type: "dm".into(), + service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong { + uri: "https://localhost:7037".into(), + accept: vec!["didcomm/v2".into()], + routing_keys: vec![], + }), + id: None, + }]; + + DIDPeer::create_peer_did(&keys, Some(&services)).unwrap(); + } + + #[tokio::test] + async fn create_peer_did_works_ed25519_without_passing_pub_key() { + let (_, _, keys) = _get_keys(Some(DIDPeerKeyType::Ed25519), false); + + // Create a service definition + let services = vec![DIDPeerService { + _type: "dm".into(), + service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong { + uri: "https://localhost:7037".into(), + accept: vec!["didcomm/v2".into()], + routing_keys: vec![], + }), + id: None, + }]; + + let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap(); + let parts: Vec<&str> = did.split(":").collect(); + let method_ids: Vec<&str> = parts[2].split(".").collect(); + + assert_eq!(parts.len(), 3); + assert_eq!(parts[1], "peer"); + assert_eq!(method_ids.first().unwrap().parse::().unwrap(), 2); + assert_eq!(method_ids.len(), 4); + } + + #[tokio::test] + async fn create_peer_did_works_p256_without_passing_pub_key() { + let (_, _, keys) = _get_keys(Some(DIDPeerKeyType::P256), false); + + // Create a service definition + let services = vec![DIDPeerService { + _type: "dm".into(), + service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong { + uri: "https://localhost:7037".into(), + accept: vec!["didcomm/v2".into()], + routing_keys: vec![], + }), + id: None, + }]; + + let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap(); + let parts: Vec<&str> = did.split(":").collect(); + let method_ids: Vec<&str> = parts[2].split(".").collect(); + + assert_eq!(parts.len(), 3); + assert_eq!(parts[1], "peer"); + assert_eq!(method_ids.first().unwrap().parse::().unwrap(), 2); + assert_eq!(method_ids.len(), 4); + } + + #[tokio::test] + async fn create_peer_did_works_secp256k1_without_passing_pub_key() { + let (_, _, keys) = _get_keys(Some(DIDPeerKeyType::Secp256k1), false); + + // Create a service definition + let services = vec![DIDPeerService { + _type: "dm".into(), + service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong { + uri: "https://localhost:7037".into(), + accept: vec!["didcomm/v2".into()], + routing_keys: vec![], + }), + id: None, + }]; + + let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap(); + let parts: Vec<&str> = did.split(":").collect(); + let method_ids: Vec<&str> = parts[2].split(".").collect(); + + assert_eq!(parts.len(), 3); + assert_eq!(parts[1], "peer"); + assert_eq!(method_ids.first().unwrap().parse::().unwrap(), 2); + assert_eq!(method_ids.len(), 4); + } + + #[tokio::test] + async fn create_peer_did_works_ed25519() { + let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::Ed25519), true); + + // Create a service definition + let services = vec![DIDPeerService { + _type: "dm".into(), + service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong { + uri: "https://localhost:7037".into(), + accept: vec!["didcomm/v2".into()], + routing_keys: vec![], + }), + id: None, + }]; + + let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap(); + let parts: Vec<&str> = did.split(":").collect(); + let mut method_ids: Vec<&str> = parts[2].split(".").collect(); + method_ids = method_ids[1..].to_vec(); + let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()]; + + for i in 0..2 { + assert!(keys_multibase.contains(&method_ids[i][1..].to_string())); + } + assert_eq!(parts.len(), 3); + assert_eq!(parts[1], "peer"); + } + + #[tokio::test] + async fn create_peer_did_works_p256() { + let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::P256), true); + // Create a service definition + let services = vec![DIDPeerService { + _type: "dm".into(), + service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong { + uri: "https://localhost:7037".into(), + accept: vec!["didcomm/v2".into()], + routing_keys: vec![], + }), + id: None, + }]; + + let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap(); + let parts: Vec<&str> = did.split(":").collect(); + let mut method_ids: Vec<&str> = parts[2].split(".").collect(); + method_ids = method_ids[1..].to_vec(); + let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()]; + + for i in 0..2 { + assert!(keys_multibase.contains(&method_ids[i][1..].to_string())); + } + assert_eq!(parts.len(), 3); + assert_eq!(parts[1], "peer"); + } + + #[tokio::test] + async fn create_peer_did_works_secp256k1() { + let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::Secp256k1), true); + // Create a service definition + let services = vec![DIDPeerService { + _type: "dm".into(), + service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong { + uri: "https://localhost:7037".into(), + accept: vec!["didcomm/v2".into()], + routing_keys: vec![], + }), + id: None, + }]; + + let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap(); + let parts: Vec<&str> = did.split(":").collect(); + let mut method_ids: Vec<&str> = parts[2].split(".").collect(); + method_ids = method_ids[1..].to_vec(); + let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()]; + + for i in 0..2 { + assert!(keys_multibase.contains(&method_ids[i][1..].to_string())); + } + assert_eq!(parts.len(), 3); + assert_eq!(parts[1], "peer"); + } + + fn _get_keys( + key_type: Option, + with_pub_key: bool, + ) -> (DIDBuf, DIDBuf, Vec) { + let encryption_key = match key_type { + Some(DIDPeerKeyType::Ed25519) => JWK::generate_ed25519().unwrap(), + Some(DIDPeerKeyType::P256) => JWK::generate_p256(), + Some(DIDPeerKeyType::Secp256k1) => JWK::generate_secp256k1(), + None => JWK::generate_p384(), + }; + let verification_key = match key_type { + Some(DIDPeerKeyType::Ed25519) => JWK::generate_ed25519().unwrap(), + Some(DIDPeerKeyType::P256) => JWK::generate_p256(), + Some(DIDPeerKeyType::Secp256k1) => JWK::generate_secp256k1(), + None => JWK::generate_p384(), + }; + // Create the did:key DID's for each key above + let e_did_key = ssi::dids::DIDKey::generate(&encryption_key).unwrap(); + let v_did_key = ssi::dids::DIDKey::generate(&verification_key).unwrap(); + + // Put these keys in order and specify the type of each key (we strip the did:key: from the front) + let keys = vec![ + DIDPeerCreateKeys { + purpose: DIDPeerKeys::Verification, + type_: key_type.clone(), + public_key_multibase: if with_pub_key { + Some(v_did_key[8..].to_string()) + } else { + None + }, + }, + DIDPeerCreateKeys { + purpose: DIDPeerKeys::Encryption, + type_: key_type.clone(), + public_key_multibase: if with_pub_key { + Some(e_did_key[8..].to_string()) + } else { + None + }, + }, + ]; + + (e_did_key, v_did_key, keys) + } +} + // ********************************************************************************************************************************** // WASM Specific structs and code // ********************************************************************************************************************************** From 5c45e391b457d45e9596732edd436b05e57e0f76 Mon Sep 17 00:00:00 2001 From: YoussefAWasfy Date: Thu, 26 Sep 2024 12:27:13 +0200 Subject: [PATCH 2/2] test: add unit tests for expand_keys --- .../did-peer/src/lib.rs | 59 +++++++++++++++++-- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/affinidi-did-resolver-methods/did-peer/src/lib.rs b/affinidi-did-resolver-methods/did-peer/src/lib.rs index ad15be6..ac1dff4 100644 --- a/affinidi-did-resolver-methods/did-peer/src/lib.rs +++ b/affinidi-did-resolver-methods/did-peer/src/lib.rs @@ -754,13 +754,58 @@ impl DIDPeer { #[cfg(test)] mod test { - use ssi::{dids::DIDBuf, JWK}; - use crate::{ DIDPeer, DIDPeerCreateKeys, DIDPeerKeyType, DIDPeerKeys, DIDPeerService, PeerServiceEndPoint, PeerServiceEndPointLong, }; + use ssi::{ + dids::{document::DIDVerificationMethod, DIDBuf, DIDResolver, DID}, + JWK, + }; + + const DID_PEER: &str = "did:peer:2.Vz6MkiToqovww7vYtxm1xNM15u9JzqzUFZ1k7s7MazYJUyAxv.EzQ3shQLqRUza6AMJFbPuMdvFRFWm1wKviQRnQSC1fScovJN4s.SeyJ0IjoiRElEQ29tbU1lc3NhZ2luZyIsInMiOnsidXJpIjoiaHR0cHM6Ly8xMjcuMC4wLjE6NzAzNyIsImEiOlsiZGlkY29tbS92MiJdLCJyIjpbXX19"; + + #[should_panic( + expected = "Failed to convert verification_method. Reason: Missing publicKeyBase58" + )] + #[tokio::test] + async fn expand_keys_throws_key_parsing_missing_pbk58_error() { + let peer = DIDPeer; + let output = peer + .resolve(DID::new::(&DID_PEER.to_string()).unwrap()) + .await + .unwrap(); + + let mut document = output.document.document().clone(); + let mut new_vms: Vec = vec![]; + for mut vm in document.verification_method { + vm.properties.remove("publicKeyMultibase"); + new_vms.push(vm); + } + + document.verification_method = new_vms; + let _expanded_doc = DIDPeer::expand_keys(&document).await.unwrap(); + } + + #[tokio::test] + async fn expand_keys_works() { + let peer = DIDPeer; + let document = peer + .resolve(DID::new::(&DID_PEER.to_string()).unwrap()) + .await + .unwrap(); + + let vm_before_expansion = document.clone().document.verification_method.clone(); + let expanded_doc = DIDPeer::expand_keys(&document.document).await.unwrap(); + let vms_after_expansion = expanded_doc.verification_method; + + for vm in vms_after_expansion.clone() { + assert!(vm.id.starts_with("did:key")); + } + assert_eq!(vm_before_expansion.len(), vms_after_expansion.len()) + } + #[tokio::test] async fn create_peer_did_without_keys_and_services() { let keys: Vec = vec![]; @@ -848,10 +893,11 @@ mod test { id: None, }]; - let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap(); + let (did, keys) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap(); let parts: Vec<&str> = did.split(":").collect(); let method_ids: Vec<&str> = parts[2].split(".").collect(); + assert_eq!(keys.len(), 2); assert_eq!(parts.len(), 3); assert_eq!(parts[1], "peer"); assert_eq!(method_ids.first().unwrap().parse::().unwrap(), 2); @@ -873,10 +919,11 @@ mod test { id: None, }]; - let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap(); + let (did, keys) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap(); let parts: Vec<&str> = did.split(":").collect(); let method_ids: Vec<&str> = parts[2].split(".").collect(); + assert_eq!(keys.len(), 2); assert_eq!(parts.len(), 3); assert_eq!(parts[1], "peer"); assert_eq!(method_ids.first().unwrap().parse::().unwrap(), 2); @@ -898,10 +945,12 @@ mod test { id: None, }]; - let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap(); + let (did, keys) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap(); + let parts: Vec<&str> = did.split(":").collect(); let method_ids: Vec<&str> = parts[2].split(".").collect(); + assert_eq!(keys.len(), 2); assert_eq!(parts.len(), 3); assert_eq!(parts[1], "peer"); assert_eq!(method_ids.first().unwrap().parse::().unwrap(), 2);