diff --git a/aries/aries_vcx/src/protocols/did_exchange/mod.rs b/aries/aries_vcx/src/protocols/did_exchange/mod.rs index 770a3eda6d..71769b1408 100644 --- a/aries/aries_vcx/src/protocols/did_exchange/mod.rs +++ b/aries/aries_vcx/src/protocols/did_exchange/mod.rs @@ -1,17 +1,83 @@ use std::sync::Arc; +use did_doc::schema::{ + did_doc::DidDocument, + verification_method::{VerificationMethod, VerificationMethodKind}, +}; +use did_parser::DidUrl; use did_resolver_registry::ResolverRegistry; use messages::msg_fields::protocols::out_of_band::invitation::{ Invitation as OobInvitation, OobService, }; use public_key::Key; -use crate::errors::error::{AriesVcxError, AriesVcxErrorKind}; +use crate::errors::error::{AriesVcxError, AriesVcxErrorKind, VcxResult}; pub mod state_machine; pub mod states; pub mod transition; +fn resolve_verification_method( + did_doc: &DidDocument, + verification_method_ref: &DidUrl, +) -> Result { + let key = did_doc.verification_method().iter().find(|key_agreement| { + let reference_fragment = match verification_method_ref.fragment() { + None => { + warn!( + "Fragment not found in verification method reference {}", + verification_method_ref + ); + return false; + } + Some(fragment) => fragment, + }; + let key_agreement_fragment = match key_agreement.id().fragment() { + None => { + warn!( + "Fragment not found in verification method {}", + key_agreement.id() + ); + return false; + } + Some(fragment) => fragment, + }; + reference_fragment == key_agreement_fragment + }); + match key { + None => Err(AriesVcxError::from_msg( + AriesVcxErrorKind::InvalidState, + format!( + "Verification method not found in resolved did document {}", + did_doc + ), + )), + Some(verification_method) => Ok(verification_method.clone()), + } +} + +fn resolve_first_key_agreement(did_document: &DidDocument) -> VcxResult { + // todo: did_document needs robust way to resolve this, I shouldn't care if there's reference or + // actual key in the key_agreement Abstract the user from format/structure of the did + // document + let verification_method_kind = did_document.key_agreement().first().ok_or_else(|| { + AriesVcxError::from_msg( + AriesVcxErrorKind::InvalidState, + format!( + "No verification method found in resolved did document {}", + did_document + ), + ) + })?; + let verification_method = match verification_method_kind { + VerificationMethodKind::Resolved(verification_method) => verification_method.clone(), + VerificationMethodKind::Resolvable(verification_method_ref) => { + resolve_verification_method(did_document, verification_method_ref)? + } + }; + Ok(verification_method) +} + pub async fn resolve_enc_key_from_invitation( invitation: &OobInvitation, resolver_registry: &Arc, @@ -37,17 +103,8 @@ pub async fn resolve_enc_key_from_invitation( "resolve_enc_key_from_invitation >> Resolved did document {}", output.did_document ); - Ok(output - .did_document - .verification_method() - .first() - .ok_or_else(|| { - AriesVcxError::from_msg( - AriesVcxErrorKind::InvalidState, - format!("No verification method found in resolved did document {}", &output.did_document), - ) - })? - .public_key()?) + let key = resolve_first_key_agreement(&output.did_document)?; + Ok(key.public_key()?) } OobService::AriesService(_service) => { unimplemented!("Embedded Aries Service not yet supported by did-exchange") diff --git a/did_core/did_methods/did_resolver_sov/src/resolution/utils.rs b/did_core/did_methods/did_resolver_sov/src/resolution/utils.rs index dc649059b7..eca2da3423 100644 --- a/did_core/did_methods/did_resolver_sov/src/resolution/utils.rs +++ b/did_core/did_methods/did_resolver_sov/src/resolution/utils.rs @@ -7,7 +7,7 @@ use did_resolver::{ utils::OneOrList, verification_method::{VerificationMethod, VerificationMethodType}, }, - did_parser::Did, + did_parser::{Did, DidUrl}, shared_types::did_document_metadata::DidDocumentMetadata, traits::resolvable::{ resolution_metadata::DidResolutionMetadata, resolution_output::DidResolutionOutput, @@ -96,7 +96,7 @@ pub(super) async fn ledger_response_to_ddo( // TODO: Use multibase instead of base58 let verification_method = VerificationMethod::builder( - did.to_string().try_into()?, + DidUrl::parse("#1".to_string())?, did.to_string().try_into()?, VerificationMethodType::Ed25519VerificationKey2018, ) @@ -106,6 +106,7 @@ pub(super) async fn ledger_response_to_ddo( let ddo = DidDocument::builder(ddo_id) .add_service(service) .add_verification_method(verification_method) + .add_key_agreement_reference(DidUrl::parse("#1".to_string())?) .build(); let ddo_metadata = {