Skip to content

Commit

Permalink
improve VM handling to understand more DIDDoc styles (acapy AATH test…
Browse files Browse the repository at this point in the history
…ing)

Signed-off-by: George Mulhearn <[email protected]>
  • Loading branch information
gmulhearn-anonyome committed Jun 20, 2024
1 parent c173cda commit 55a7991
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,16 @@ pub async fn create_peer_did_4(

info!("Prepared service for peer:did:4 generation: {} ", service);
let vm_ka = DidPeer4VerificationMethod::builder()
.id(vm_ka_id)
.id(vm_ka_id.clone())
.verification_method_type(VerificationMethodType::Ed25519VerificationKey2020)
.public_key(PublicKeyField::Multibase {
public_key_multibase: key_enc.fingerprint(),
})
.build();
let mut construction_did_doc = DidPeer4ConstructionDidDocument::new();
construction_did_doc.add_key_agreement(vm_ka);
construction_did_doc.add_verification_method(vm_ka);
construction_did_doc.add_key_agreement_ref(vm_ka_id);

construction_did_doc.add_service(service);

info!(
Expand Down
52 changes: 40 additions & 12 deletions aries/aries_vcx/src/utils/didcomm_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ fn resolve_service_key_to_typed_key(
}
}

/// Resolves the first ed25519 base58 public key (a.k.a. verkey) within the DIDDocuments key agreement
/// keys. Useful for resolving keys that can be used for packing DIDCommV1 messages.
/// Resolves the first ed25519 base58 public key (a.k.a. verkey) within the DIDDocuments key
/// agreement keys. Useful for resolving keys that can be used for packing DIDCommV1 messages.
pub fn resolve_ed25519_base58_key_agreement(did_document: &DidDocument) -> VcxResult<String> {
let vm_types = [
VerificationMethodType::Ed25519VerificationKey2018,
Expand All @@ -61,17 +61,45 @@ pub fn resolve_ed25519_base58_key_agreement(did_document: &DidDocument) -> VcxRe
Ok(vm.public_key()?.base58())
}

pub fn get_routing_keys(their_did_doc: &DidDocument, service_id: &Uri) -> VcxResult<Vec<String>> {
pub fn get_ed25519_base58_routing_keys(
their_did_doc: &DidDocument,
service_id: &Uri,
) -> VcxResult<Vec<String>> {
let service = their_did_doc.get_service_by_id(service_id)?;
match service.extra_field_routing_keys() {
Ok(routing_keys) => {
let mut naked_routing_keys = Vec::new();
for key in routing_keys.iter() {
naked_routing_keys
.push(resolve_service_key_to_typed_key(key, their_did_doc)?.base58());
}
Ok(naked_routing_keys)
let Ok(routing_keys) = service.extra_field_routing_keys() else {
return Ok(vec![]);
};

let mut naked_routing_keys = Vec::new();

for key in routing_keys.iter() {
let pub_key = resolve_service_key_to_typed_key(key, their_did_doc)?;

if pub_key.key_type() == &KeyType::Ed25519 {
naked_routing_keys.push(pub_key.base58());
}
}

Ok(naked_routing_keys)
}

pub fn get_ed25519_base58_recipient_keys(
their_did_doc: &DidDocument,
service_id: &Uri,
) -> VcxResult<Vec<String>> {
let service = their_did_doc.get_service_by_id(service_id)?;
let Ok(recipient_keys) = service.extra_field_recipient_keys() else {
return Ok(vec![]);
};

let mut naked_recipient_keys = Vec::new();

for key in recipient_keys.iter() {
let pub_key = resolve_service_key_to_typed_key(key, their_did_doc)?;
if pub_key.key_type() == &KeyType::Ed25519 {
naked_recipient_keys.push(pub_key.base58());
}
Err(_err) => Ok(Vec::new()),
}

Ok(naked_recipient_keys)
}
19 changes: 14 additions & 5 deletions aries/aries_vcx/src/utils/encryption_envelope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ use messages::{
use public_key::{Key, KeyType};
use uuid::Uuid;

use super::didcomm_utils::get_ed25519_base58_recipient_keys;
use crate::{
errors::error::prelude::*,
utils::didcomm_utils::{get_routing_keys, resolve_ed25519_base58_key_agreement},
utils::didcomm_utils::{get_ed25519_base58_routing_keys, resolve_ed25519_base58_key_agreement},
};

#[derive(Debug)]
Expand Down Expand Up @@ -63,9 +64,16 @@ impl EncryptionEnvelope {
their_service_id: &Uri,
) -> VcxResult<EncryptionEnvelope> {
let sender_vk = resolve_ed25519_base58_key_agreement(our_did_doc)?;
// CONSIDER - or should recipient keys be resolved from the service? similar to get_routing_keys.
let recipient_key = resolve_ed25519_base58_key_agreement(their_did_doc)?;
let routing_keys = get_routing_keys(their_did_doc, their_service_id)?;

let recipient_key = {
let service_keys = get_ed25519_base58_recipient_keys(their_did_doc, their_service_id)?;
match service_keys.into_iter().next() {
Some(key) => key,
// as a backup, use the first key agreement key, or none
None => resolve_ed25519_base58_key_agreement(their_did_doc)?,
}
};
let routing_keys = get_ed25519_base58_routing_keys(their_did_doc, their_service_id)?;

EncryptionEnvelope::create_from_keys(
wallet,
Expand All @@ -81,7 +89,8 @@ impl EncryptionEnvelope {
wallet: &impl BaseWallet,
data: &[u8],
sender_vk: Option<&str>,
// TODO - why not have encryption envelope take typed [Key]s, and enforce they are KeyType::Ed25519
// TODO - why not have encryption envelope take typed [Key]s, and enforce they are
// KeyType::Ed25519
recipient_key: String,
routing_keys: Vec<String>,
) -> VcxResult<EncryptionEnvelope> {
Expand Down
25 changes: 23 additions & 2 deletions did_core/did_doc/src/schema/did_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,31 @@ impl DidDocument {
self.extra.get(key)
}

/// Scan the DIDDocument for a [VerificationMethod] that matches the given reference.
pub fn dereference_key(&self, reference: &DidUrl) -> Option<&VerificationMethod> {
self.verification_method
let vms = self.verification_method.iter();

// keys are typically in the VMs ^, but may be embedded in the other fields:
let assertions = self.assertion_method.iter().filter_map(|k| k.resolved());
let key_agreements = self.key_agreement.iter().filter_map(|k| k.resolved());
let authentications = self.authentication.iter().filter_map(|k| k.resolved());
let cap_invocations = self
.capability_invocation
.iter()
.filter_map(|k| k.resolved());
let cap_delegations = self
.capability_delegation
.iter()
.find(|vm| vm.id().fragment() == reference.fragment())
.filter_map(|k| k.resolved());

let mut all_vms = vms
.chain(assertions)
.chain(key_agreements)
.chain(authentications)
.chain(cap_invocations)
.chain(cap_delegations);

all_vms.find(|vm| vm.id().fragment() == reference.fragment())
}

pub fn validate(&self) -> Result<(), DidDocumentBuilderError> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,13 @@ pub enum VerificationMethodKind {
Resolved(VerificationMethod),
Resolvable(DidUrl),
}

impl VerificationMethodKind {
/// Convenience function to try get the resolved enum variant (if it is that variant)
pub fn resolved(&self) -> Option<&VerificationMethod> {
match &self {
VerificationMethodKind::Resolved(x) => Some(x),
VerificationMethodKind::Resolvable(_) => None,
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,9 @@ impl DidPeer4ConstructionDidDocument {
.push(DidPeer4VerificationMethodKind::Resolved(method));
}

pub fn add_key_agreement_ref(&mut self, refernece: DidUrl) {
pub fn add_key_agreement_ref(&mut self, reference: DidUrl) {
self.key_agreement
.push(DidPeer4VerificationMethodKind::Resolvable(refernece));
.push(DidPeer4VerificationMethodKind::Resolvable(reference));
}

pub fn add_capability_invocation(&mut self, method: DidPeer4VerificationMethod) {
Expand Down

0 comments on commit 55a7991

Please sign in to comment.