Skip to content

Commit

Permalink
did:peer:4 integration, bugfix, improvements (hyperledger#1167)
Browse files Browse the repository at this point in the history
* did:peer:4 integration, bugfix, improvements (hyperledger#1167)

Signed-off-by: Patrik Stas <patrik.stas@absa.africa>
  • Loading branch information
Patrik-Stas authored and GHkrishna committed Apr 16, 2024
1 parent 8d274c9 commit c7d9e4b
Show file tree
Hide file tree
Showing 18 changed files with 312 additions and 261 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions aries/agents/aath-backchannel/src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ async fn download_genesis_file() -> std::result::Result<String, String> {
let mut f = std::fs::OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(path.clone())
.expect("Unable to open file");
f.write_all(body.as_bytes()).expect("Unable to write data");
Expand Down
21 changes: 9 additions & 12 deletions aries/agents/aries-vcx-agent/src/handlers/did_exchange.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ use aries_vcx::{
protocols::did_exchange::{
resolve_enc_key_from_invitation,
state_machine::{
create_our_did_document,
generic::{GenericDidExchange, ThinState},
helpers::create_peer_did_4,
},
},
transport::Transport,
utils::encryption_envelope::EncryptionEnvelope,
};
use aries_vcx_core::wallet::base_wallet::BaseWallet;
use did_peer::peer_did::{numalgos::numalgo2::Numalgo2, PeerDid};
use did_resolver_registry::ResolverRegistry;
use did_resolver_sov::did_resolver::did_doc::schema::did_doc::DidDocument;
use url::Url;
Expand Down Expand Up @@ -66,12 +65,10 @@ impl<T: BaseWallet> DidcommHandlerDidExchange<T> {
invitation_id: Option<String>,
) -> AgentResult<(String, Option<String>)> {
// todo: type the return type
let (our_did_document, _our_verkey) =
create_our_did_document(self.wallet.as_ref(), self.service_endpoint.clone(), vec![])
.await?;
let (our_peer_did, _our_verkey) =
create_peer_did_4(self.wallet.as_ref(), self.service_endpoint.clone(), vec![]).await?;

let their_did: Did = their_did.parse()?;
let our_peer_did = PeerDid::<Numalgo2>::from_did_doc(our_did_document.clone())?;
let (requester, request) = GenericDidExchange::construct_request(
self.resolver_registry.clone(),
invitation_id,
Expand Down Expand Up @@ -168,10 +165,8 @@ impl<T: BaseWallet> DidcommHandlerDidExchange<T> {
}
};

let (our_did_document, _our_verkey) =
create_our_did_document(self.wallet.as_ref(), self.service_endpoint.clone(), vec![])
.await?;
let peer_did_invitee = PeerDid::<Numalgo2>::from_did_doc(our_did_document.clone())?;
let (peer_did_4_invitee, _our_verkey) =
create_peer_did_4(self.wallet.as_ref(), self.service_endpoint.clone(), vec![]).await?;

let pthid = request
.clone()
Expand All @@ -190,7 +185,7 @@ impl<T: BaseWallet> DidcommHandlerDidExchange<T> {
self.wallet.as_ref(),
self.resolver_registry.clone(),
request,
&peer_did_invitee,
&peer_did_4_invitee,
invitation_key,
)
.await?;
Expand Down Expand Up @@ -235,7 +230,9 @@ impl<T: BaseWallet> DidcommHandlerDidExchange<T> {

let (requester, _) = self.did_exchange.get(&thid)?;

let (requester, complete) = requester.handle_response(response).await?;
let (requester, complete) = requester
.handle_response(response, self.resolver_registry.clone())
.await?;
let ddo_their = requester.their_did_doc();
let ddo_our = requester.our_did_document();
let service = ddo_their.get_service_of_type(&ServiceType::DIDCommV1)?;
Expand Down
9 changes: 3 additions & 6 deletions aries/agents/aries-vcx-agent/src/handlers/out_of_band.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@ use aries_vcx::{
},
AriesMessage,
},
protocols::did_exchange::state_machine::create_our_did_document,
protocols::did_exchange::state_machine::helpers::create_peer_did_4,
};
use aries_vcx_core::wallet::base_wallet::BaseWallet;
use did_peer::peer_did::{numalgos::numalgo2::Numalgo2, PeerDid};
use url::Url;

use crate::{
Expand All @@ -39,10 +38,8 @@ impl<T: BaseWallet> ServiceOutOfBand<T> {
}

pub async fn create_invitation(&self) -> AgentResult<AriesMessage> {
let (our_did_document, _our_verkey) =
create_our_did_document(self.wallet.as_ref(), self.service_endpoint.clone(), vec![])
.await?;
let peer_did = PeerDid::<Numalgo2>::from_did_doc(our_did_document)?;
let (peer_did, _our_verkey) =
create_peer_did_4(self.wallet.as_ref(), self.service_endpoint.clone(), vec![]).await?;

let sender = OutOfBandSender::create()
.append_service(&OobService::Did(peer_did.to_string()))
Expand Down
1 change: 1 addition & 0 deletions aries/aries_vcx/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,4 @@ test_utils = { path = "../misc/test_utils" }
wallet_migrator = { path = "../misc/wallet_migrator" }
async-channel = "1.7.1"
tokio = { version = "1.20", features = ["rt", "macros", "rt-multi-thread"] }
pretty_assertions = "1.4.0"
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::sync::Arc;
use aries_vcx_core::wallet::base_wallet::BaseWallet;
use did_doc::schema::did_doc::DidDocument;
use did_parser_nom::Did;
use did_peer::peer_did::{numalgos::numalgo2::Numalgo2, PeerDid};
use did_peer::peer_did::{numalgos::numalgo4::Numalgo4, PeerDid};
use did_resolver_registry::ResolverRegistry;
use messages::msg_fields::protocols::did_exchange::{
complete::Complete, problem_report::ProblemReport, request::Request, response::Response,
Expand Down Expand Up @@ -87,7 +87,7 @@ impl GenericDidExchange {
resolver_registry: Arc<ResolverRegistry>,
invitation_id: Option<String>,
their_did: &Did,
our_peer_did: &PeerDid<Numalgo2>,
our_peer_did: &PeerDid<Numalgo4>,
) -> Result<(Self, Request), AriesVcxError> {
let TransitionResult { state, output } =
DidExchangeRequester::<RequestSent>::construct_request(
Expand All @@ -107,7 +107,7 @@ impl GenericDidExchange {
wallet: &impl BaseWallet,
resolver_registry: Arc<ResolverRegistry>,
request: Request,
our_peer_did: &PeerDid<Numalgo2>,
our_peer_did: &PeerDid<Numalgo4>,
invitation_key: Option<Key>,
) -> Result<(Self, Response), AriesVcxError> {
let TransitionResult { state, output } =
Expand All @@ -128,11 +128,15 @@ impl GenericDidExchange {
pub async fn handle_response(
self,
response: Response,
resolver_registry: Arc<ResolverRegistry>,
) -> Result<(Self, Complete), (Self, AriesVcxError)> {
match self {
GenericDidExchange::Requester(requester_state) => match requester_state {
RequesterState::RequestSent(request_sent_state) => {
match request_sent_state.receive_response(response).await {
match request_sent_state
.receive_response(response, resolver_registry)
.await
{
Ok(TransitionResult { state, output }) => Ok((
GenericDidExchange::Requester(RequesterState::Completed(state)),
output,
Expand Down
133 changes: 32 additions & 101 deletions aries/aries_vcx/src/protocols/did_exchange/state_machine/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@ use did_doc::schema::{
did_doc::DidDocument,
service::{service_key_kind::ServiceKeyKind, typed::didcommv1::ServiceDidCommV1, Service},
types::uri::Uri,
verification_method::{PublicKeyField, VerificationMethod, VerificationMethodType},
verification_method::{PublicKeyField, VerificationMethodType},
};
use did_key::DidKey;
use did_parser_nom::{Did, DidUrl};
use did_peer::peer_did::{numalgos::numalgo2::Numalgo2, PeerDid};
use did_parser_nom::DidUrl;
use did_peer::peer_did::{
numalgos::numalgo4::{
construction_did_doc::{DidPeer4ConstructionDidDocument, DidPeer4VerificationMethod},
Numalgo4,
},
PeerDid,
};
use messages::{
decorators::{
attachment::{Attachment, AttachmentData, AttachmentType},
Expand All @@ -35,7 +41,7 @@ use crate::{
},
};

pub fn construct_response(
pub(crate) fn construct_response(
request_id: String,
our_did_document: &DidDocument,
signed_attach: Attachment,
Expand All @@ -55,19 +61,19 @@ pub fn construct_response(
.build()
}

pub async fn generate_keypair(
async fn generate_keypair(
wallet: &impl BaseWallet,
key_type: KeyType,
) -> Result<Key, AriesVcxError> {
let pairwise_info = PairwiseInfo::create(wallet).await?;
Ok(Key::from_base58(&pairwise_info.pw_vk, key_type)?)
}

pub async fn create_our_did_document(
pub async fn create_peer_did_4(
wallet: &impl BaseWallet,
service_endpoint: Url,
routing_keys: Vec<String>,
) -> Result<(DidDocument, Key), AriesVcxError> {
) -> Result<(PeerDid<Numalgo4>, Key), AriesVcxError> {
let key_enc = generate_keypair(wallet, KeyType::Ed25519).await?;

let service: Service = ServiceDidCommV1::new(
Expand All @@ -82,38 +88,29 @@ pub async fn create_our_did_document(
)
.try_into()?;

info!("Prepared service for peer:did:2 generation: {} ", service);
let mut did_document = did_doc_from_keys(Default::default(), key_enc.clone(), service)?;
info!(
"Created did document for peer:did:2 generation: {} ",
did_document
);
let peer_did = PeerDid::<Numalgo2>::from_did_doc(did_document.clone())?;
did_document.set_id(peer_did.did().clone());
Ok((did_document, key_enc))
}

fn did_doc_from_keys(
did: Did,
key_enc: Key,
service: Service,
) -> Result<DidDocument, AriesVcxError> {
let vm_ka_id = DidUrl::from_fragment(key_enc.short_prefixless_fingerprint())?;
let vm_ka = VerificationMethod::builder()
.id(vm_ka_id)
.controller(did.clone())
info!("Prepared service for peer:did:4 generation: {} ", service);
let vm_ka = DidPeer4VerificationMethod::builder()
.id(DidUrl::from_fragment("key1".to_string())?)
.verification_method_type(VerificationMethodType::Ed25519VerificationKey2020)
.public_key(PublicKeyField::Base58 {
public_key_base58: key_enc.base58(),
})
.build();
let mut did_doc = DidDocument::new(did);
did_doc.add_service(service);
did_doc.add_key_agreement(vm_ka);
Ok(did_doc)
let mut construction_did_doc = DidPeer4ConstructionDidDocument::new();
construction_did_doc.add_key_agreement(vm_ka);
construction_did_doc.add_service(service);

info!(
"Created did document for peer:did:4 generation: {} ",
construction_did_doc
);
let peer_did = PeerDid::<Numalgo4>::new(construction_did_doc)?;
info!("Created peer did: {peer_did}");

Ok((peer_did, key_enc))
}

pub fn ddo_to_attach(ddo: DidDocument) -> Result<Attachment, AriesVcxError> {
pub(crate) fn ddo_to_attach(ddo: DidDocument) -> Result<Attachment, AriesVcxError> {
// Interop note: acapy accepts unsigned when using peer dids?
let content_b64 =
base64::engine::Engine::encode(&URL_SAFE_NO_PAD, serde_json::to_string(&ddo)?);
Expand All @@ -128,7 +125,7 @@ pub fn ddo_to_attach(ddo: DidDocument) -> Result<Attachment, AriesVcxError> {

// TODO: Obviously, extract attachment signing
// TODO: JWS verification
pub async fn jws_sign_attach(
pub(crate) async fn jws_sign_attach(
mut attach: Attachment,
verkey: Key,
wallet: &impl BaseWallet,
Expand Down Expand Up @@ -173,7 +170,7 @@ pub async fn jws_sign_attach(
}
}

pub fn attachment_to_diddoc(attachment: Attachment) -> Result<DidDocument, AriesVcxError> {
pub(crate) fn attachment_to_diddoc(attachment: Attachment) -> Result<DidDocument, AriesVcxError> {
match attachment.data.content {
AttachmentType::Json(value) => serde_json::from_value(value).map_err(Into::into),
AttachmentType::Base64(ref value) => {
Expand All @@ -194,7 +191,7 @@ pub fn attachment_to_diddoc(attachment: Attachment) -> Result<DidDocument, Aries
}
}

pub fn to_transition_error<S, T>(state: S) -> impl FnOnce(T) -> TransitionError<S>
pub(crate) fn to_transition_error<S, T>(state: S) -> impl FnOnce(T) -> TransitionError<S>
where
T: Into<AriesVcxError>,
{
Expand All @@ -203,69 +200,3 @@ where
state,
}
}

#[cfg(test)]
mod tests {
use did_doc::schema::{
service::typed::ServiceType, utils::OneOrList, verification_method::VerificationMethodKind,
};

use super::*;

#[tokio::test]
async fn test_did_doc_from_keys() {
let key_enc = Key::new(
"tyntrez7bCthPqvZUDGwhYB1bSe9HzpLdSeHFpuSwst".into(),
KeyType::Ed25519,
)
.unwrap();

let service_endpoint = Url::parse("http://example.com").unwrap();
let routing_keys = vec![
ServiceKeyKind::Value("routing_key1".into()),
ServiceKeyKind::Value("routing_key2".into()),
];
let service: Service = ServiceDidCommV1::new(
Uri::new("#service-0").unwrap(),
service_endpoint.clone(),
0,
vec![],
routing_keys,
)
.try_into()
.unwrap();

let did = Did::default();

let result = did_doc_from_keys(did, key_enc.clone(), service);

assert!(result.is_ok());
let did_doc = result.unwrap();

assert_eq!(did_doc.service().len(), 1);
let ddo_service = did_doc.service().first().unwrap();
assert_eq!(&ddo_service.id().to_string(), "#service-0");
assert_eq!(
ddo_service.service_type(),
&OneOrList::One(ServiceType::DIDCommV1)
);
assert_eq!(ddo_service.service_endpoint(), &service_endpoint);
assert_eq!(
ddo_service.extra_field_routing_keys().unwrap(),
vec![
ServiceKeyKind::Value("routing_key1".into()),
ServiceKeyKind::Value("routing_key2".into())
]
);

assert_eq!(did_doc.key_agreement().len(), 1);
match did_doc.key_agreement().first().unwrap() {
VerificationMethodKind::Resolved(key_agreement) => {
assert_eq!(key_agreement.public_key().unwrap(), key_enc);
}
VerificationMethodKind::Resolvable(_) => {
panic!("Key agreement was expected to have embedded key");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mod helpers;
pub mod helpers;

pub mod generic;
pub mod requester;
Expand All @@ -8,7 +8,6 @@ use std::marker::PhantomData;

use chrono::Utc;
use did_doc::schema::did_doc::DidDocument;
pub use helpers::{create_our_did_document, generate_keypair};
use messages::{
decorators::{thread::Thread, timing::Timing},
msg_fields::protocols::did_exchange::problem_report::{
Expand Down
Loading

0 comments on commit c7d9e4b

Please sign in to comment.