From d9046e153e8a940d3e437df4c43f0fc2ee931b84 Mon Sep 17 00:00:00 2001 From: Adam Mika Date: Thu, 30 Nov 2023 12:36:05 -0700 Subject: [PATCH 1/2] Create and resolve did:key --- crates/dids/Cargo.toml | 1 + crates/dids/src/method/key.rs | 119 ++++++++++++++++++++++++++++++++++ crates/dids/src/method/mod.rs | 1 + crates/dids/src/resolver.rs | 12 ++++ 4 files changed, 133 insertions(+) create mode 100644 crates/dids/src/method/key.rs diff --git a/crates/dids/Cargo.toml b/crates/dids/Cargo.toml index df0166f2..4767a508 100644 --- a/crates/dids/Cargo.toml +++ b/crates/dids/Cargo.toml @@ -10,6 +10,7 @@ license-file.workspace = true async-trait = "0.1.74" crypto = { path = "../crypto" } did-jwk = "0.1.1" +did-method-key = "0.2.2" did-web = "0.2.2" serde = { workspace = true } serde_json = { workspace = true } diff --git a/crates/dids/src/method/key.rs b/crates/dids/src/method/key.rs new file mode 100644 index 00000000..92248bfa --- /dev/null +++ b/crates/dids/src/method/key.rs @@ -0,0 +1,119 @@ +use crate::did::Did; +use crate::method::{DidMethod, DidMethodError, DidResolutionResult}; +use async_trait::async_trait; +use crypto::key::{Key, KeyType}; +use crypto::key_manager::KeyManager; +use did_method_key::DIDKey as SpruceDidKeyMethod; +use ssi_dids::did_resolve::{DIDResolver, ResolutionInputMetadata}; +use ssi_dids::{DIDMethod, Source}; +use std::sync::Arc; + +/// Concrete implementation for a did:key DID +pub struct DidKey { + uri: String, + key_manager: Arc, +} + +pub struct DidKeyCreateOptions { + pub key_type: KeyType, +} + +impl Did for DidKey { + fn uri(&self) -> &str { + &self.uri + } + + fn key_manager(&self) -> &Arc { + &self.key_manager + } +} + +#[async_trait] +impl DidMethod for DidKey { + const NAME: &'static str = "key"; + + fn create( + key_manager: Arc, + options: DidKeyCreateOptions, + ) -> Result { + let key_alias = key_manager.generate_private_key(options.key_type)?; + let public_key = + key_manager + .get_public_key(&key_alias)? + .ok_or(DidMethodError::DidCreationFailure( + "PublicKey not found".to_string(), + ))?; + + let uri = SpruceDidKeyMethod + .generate(&Source::Key(public_key.jwk())) + .ok_or(DidMethodError::DidCreationFailure( + "Failed to generate did:key".to_string(), + ))?; + + Ok(DidKey { uri, key_manager }) + } + + async fn resolve_uri(did_uri: &str) -> DidResolutionResult { + let input_metadata = ResolutionInputMetadata::default(); + let (did_resolution_metadata, did_document, did_document_metadata) = + SpruceDidKeyMethod.resolve(did_uri, &input_metadata).await; + + DidResolutionResult { + did_resolution_metadata, + did_document, + did_document_metadata, + ..Default::default() + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crypto::key_manager::local_key_manager::LocalKeyManager; + use ssi_dids::did_resolve::ERROR_INVALID_DID; + + fn create_did_key() -> DidKey { + let key_manager = Arc::new(LocalKeyManager::new_in_memory()); + let options = DidKeyCreateOptions { + key_type: KeyType::Ed25519, + }; + + DidKey::create(key_manager, options).expect("DidKey creation failed") + } + + #[test] + fn create_produces_correct_uri() { + let did = create_did_key(); + assert!(did.uri.starts_with("did:key:")); + } + + #[tokio::test] + async fn instance_resolve() { + let did = create_did_key(); + let result = did.resolve().await; + assert!(result.did_resolution_metadata.error.is_none()); + + let did_document = result.did_document.unwrap(); + assert_eq!(did_document.id, did.uri); + } + + #[tokio::test] + async fn resolve_uri_success() { + let did = create_did_key(); + let result = DidKey::resolve_uri(&did.uri).await; + assert!(result.did_resolution_metadata.error.is_none()); + + let did_document = result.did_document.expect("did_document not found"); + assert_eq!(did_document.id, did.uri); + } + + #[tokio::test] + async fn resolve_uri_failure() { + let result = DidKey::resolve_uri("did:key:does-not-exist").await; + assert_eq!( + result.did_resolution_metadata.error, + Some(ERROR_INVALID_DID.to_string()) + ); + } +} diff --git a/crates/dids/src/method/mod.rs b/crates/dids/src/method/mod.rs index acaabd41..4c651d85 100644 --- a/crates/dids/src/method/mod.rs +++ b/crates/dids/src/method/mod.rs @@ -1,4 +1,5 @@ pub mod jwk; +pub mod key; pub mod web; use crate::did::Did; diff --git a/crates/dids/src/resolver.rs b/crates/dids/src/resolver.rs index 7eab14e9..936e4511 100644 --- a/crates/dids/src/resolver.rs +++ b/crates/dids/src/resolver.rs @@ -1,4 +1,5 @@ use crate::method::jwk::DidJwk; +use crate::method::key::DidKey; use crate::method::web::DidWeb; use crate::method::DidMethod; use serde::{Deserialize, Serialize}; @@ -19,6 +20,7 @@ impl DidResolver { match method_name { DidJwk::NAME => DidJwk::resolve_uri(did_uri).await, + DidKey::NAME => DidKey::resolve_uri(did_uri).await, DidWeb::NAME => DidWeb::resolve_uri(did_uri).await, _ => DidResolutionResult::from_error(ERROR_METHOD_NOT_SUPPORTED), } @@ -89,6 +91,16 @@ mod tests { assert_eq!(did_document.id, did_uri); } + #[tokio::test] + async fn resolve_did_key() { + let did_uri = "did:key:zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme"; + let result = DidResolver::resolve_uri(did_uri).await; + assert!(result.did_resolution_metadata.error.is_none()); + + let did_document = result.did_document.unwrap(); + assert_eq!(did_document.id, did_uri); + } + #[tokio::test] async fn resolve_did_web() { let did_uri = "did:web:tbd.website"; From 61d2d163cac2225963275041393bfe301e405fcb Mon Sep 17 00:00:00 2001 From: Adam Mika Date: Tue, 5 Dec 2023 13:52:28 -0700 Subject: [PATCH 2/2] Test for creating did:key of each key_type --- crates/dids/src/method/key.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/crates/dids/src/method/key.rs b/crates/dids/src/method/key.rs index 92248bfa..463745cc 100644 --- a/crates/dids/src/method/key.rs +++ b/crates/dids/src/method/key.rs @@ -73,24 +73,29 @@ mod tests { use crypto::key_manager::local_key_manager::LocalKeyManager; use ssi_dids::did_resolve::ERROR_INVALID_DID; - fn create_did_key() -> DidKey { + fn create_did_key(key_type: KeyType) -> DidKey { let key_manager = Arc::new(LocalKeyManager::new_in_memory()); - let options = DidKeyCreateOptions { - key_type: KeyType::Ed25519, - }; - DidKey::create(key_manager, options).expect("DidKey creation failed") + DidKey::create(key_manager, DidKeyCreateOptions { key_type }) + .expect("DidKey creation failed") } #[test] fn create_produces_correct_uri() { - let did = create_did_key(); + let did = create_did_key(KeyType::Ed25519); assert!(did.uri.starts_with("did:key:")); } + #[test] + fn create_each_key_type() { + create_did_key(KeyType::Ed25519); + create_did_key(KeyType::Secp256k1); + create_did_key(KeyType::Secp256r1); + } + #[tokio::test] async fn instance_resolve() { - let did = create_did_key(); + let did = create_did_key(KeyType::Ed25519); let result = did.resolve().await; assert!(result.did_resolution_metadata.error.is_none()); @@ -100,7 +105,7 @@ mod tests { #[tokio::test] async fn resolve_uri_success() { - let did = create_did_key(); + let did = create_did_key(KeyType::Ed25519); let result = DidKey::resolve_uri(&did.uri).await; assert!(result.did_resolution_metadata.error.is_none());