Skip to content

Commit d0fdfcd

Browse files
committed
Make encryption envelope api more general and safer
Signed-off-by: Patrik Stas <[email protected]>
1 parent 8c284ca commit d0fdfcd

File tree

7 files changed

+100
-38
lines changed

7 files changed

+100
-38
lines changed

aries/agents/rust/aries-vcx-agent/src/services/did_exchange.rs

+33-18
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::sync::Arc;
22

33
use aries_vcx::{
4+
did_doc::schema::{service::typed::ServiceType, types::uri::Uri},
45
messages::{
56
msg_fields::protocols::{
67
did_exchange::{
@@ -25,7 +26,6 @@ use aries_vcx_core::wallet::{base_wallet::BaseWallet, indy::IndySdkWallet};
2526
use did_peer::peer_did::{numalgos::numalgo2::Numalgo2, PeerDid};
2627
use did_resolver_registry::ResolverRegistry;
2728
use did_resolver_sov::did_resolver::did_doc::schema::did_doc::DidDocument;
28-
use url::Url;
2929

3030
use super::connection::ServiceEndpoint;
3131
use crate::{
@@ -83,10 +83,17 @@ impl ServiceDidExchange {
8383
.thid;
8484
let ddo_their = requester.their_did_doc();
8585
let ddo_our = requester.our_did_document();
86-
let encryption_envelope =
87-
pairwise_encrypt(ddo_our, ddo_their, self.wallet.as_ref(), &request.into()).await?;
86+
let service = ddo_their.get_service_of_type(&ServiceType::DIDCommV1)?;
87+
let encryption_envelope = pairwise_encrypt(
88+
ddo_our,
89+
ddo_their,
90+
self.wallet.as_ref(),
91+
&request.into(),
92+
service.id(),
93+
)
94+
.await?;
8895
VcxHttpClient
89-
.send_message(encryption_envelope.0, get_first_endpoint(ddo_their)?)
96+
.send_message(encryption_envelope.0, service.service_endpoint().clone())
9097
.await?;
9198
self.did_exchange.insert(&request_id, requester.clone())
9299
}
@@ -127,10 +134,17 @@ impl ServiceDidExchange {
127134
.await?;
128135
let ddo_their = responder.their_did_doc();
129136
let ddo_our = responder.our_did_document();
130-
let encryption_envelope =
131-
pairwise_encrypt(ddo_our, ddo_their, self.wallet.as_ref(), &response.into()).await?;
137+
let service = ddo_their.get_service_of_type(&ServiceType::DIDCommV1)?;
138+
let encryption_envelope = pairwise_encrypt(
139+
ddo_our,
140+
ddo_their,
141+
self.wallet.as_ref(),
142+
&response.into(),
143+
service.id(),
144+
)
145+
.await?;
132146
VcxHttpClient
133-
.send_message(encryption_envelope.0, get_first_endpoint(ddo_their)?)
147+
.send_message(encryption_envelope.0, service.service_endpoint().clone())
134148
.await?;
135149
self.did_exchange.insert(&request_id, responder.clone())
136150
}
@@ -144,10 +158,17 @@ impl ServiceDidExchange {
144158
.await?;
145159
let ddo_their = requester.their_did_doc();
146160
let ddo_our = requester.our_did_document();
147-
let encryption_envelope =
148-
pairwise_encrypt(ddo_our, ddo_their, self.wallet.as_ref(), &complete.into()).await?;
161+
let service = ddo_their.get_service_of_type(&ServiceType::DIDCommV1)?;
162+
let encryption_envelope = pairwise_encrypt(
163+
ddo_our,
164+
ddo_their,
165+
self.wallet.as_ref(),
166+
&complete.into(),
167+
service.id(),
168+
)
169+
.await?;
149170
VcxHttpClient
150-
.send_message(encryption_envelope.0, get_first_endpoint(ddo_their)?)
171+
.send_message(encryption_envelope.0, service.service_endpoint().clone())
151172
.await?;
152173
self.did_exchange.insert(&thread_id, requester.clone())
153174
}
@@ -187,25 +208,19 @@ impl ServiceDidExchange {
187208
}
188209
}
189210

190-
pub fn get_first_endpoint(did_document: &DidDocument) -> AgentResult<Url> {
191-
let service = did_document.service().first().ok_or(AgentError::from_msg(
192-
AgentErrorKind::InvalidState,
193-
"No service found",
194-
))?;
195-
Ok(service.service_endpoint().clone())
196-
}
197-
198211
pub async fn pairwise_encrypt(
199212
our_did_doc: &DidDocument,
200213
their_did_doc: &DidDocument,
201214
wallet: &impl BaseWallet,
202215
message: &AriesMessage,
216+
their_service_id: &Uri,
203217
) -> AgentResult<EncryptionEnvelope> {
204218
EncryptionEnvelope::create(
205219
wallet,
206220
serde_json::json!(message).to_string().as_bytes(),
207221
our_did_doc,
208222
their_did_doc,
223+
their_service_id,
209224
)
210225
.await
211226
.map_err(|err| {

aries/aries_vcx/src/utils/didcomm_utils.rs

+5-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use did_doc::schema::{
2-
did_doc::DidDocument, service::service_key_kind::ServiceKeyKind,
2+
did_doc::DidDocument, service::service_key_kind::ServiceKeyKind, types::uri::Uri,
33
verification_method::VerificationMethodType,
44
};
55
use public_key::Key;
@@ -41,27 +41,18 @@ pub fn resolve_base58_key_agreement(did_document: &DidDocument) -> VcxResult<Str
4141
VerificationMethodType::X25519KeyAgreementKey2019,
4242
VerificationMethodType::X25519KeyAgreementKey2020,
4343
];
44-
let key_base58 = did_document.find_key_agreement_of_type(&key_types)?;
44+
let key_base58 = did_document.get_key_agreement_of_type(&key_types)?;
4545
Ok(key_base58.public_key()?.base58())
4646
}
4747

48-
pub fn get_routing_keys(our_did_doc: &DidDocument) -> VcxResult<Vec<String>> {
49-
let service = our_did_doc
50-
.service()
51-
.first()
52-
.ok_or_else(|| {
53-
AriesVcxError::from_msg(
54-
AriesVcxErrorKind::InvalidState,
55-
"No Service object found on our did document",
56-
)
57-
})?
58-
.clone();
48+
pub fn get_routing_keys(their_did_doc: &DidDocument, service_id: &Uri) -> VcxResult<Vec<String>> {
49+
let service = their_did_doc.get_service_by_id(service_id)?;
5950
match service.extra_field_routing_keys() {
6051
Ok(routing_keys) => {
6152
let mut naked_routing_keys = Vec::new();
6253
for key in routing_keys.iter() {
6354
naked_routing_keys
64-
.push(resolve_service_key_to_typed_key(key, our_did_doc)?.base58());
55+
.push(resolve_service_key_to_typed_key(key, their_did_doc)?.base58());
6556
}
6657
Ok(naked_routing_keys)
6758
}

aries/aries_vcx/src/utils/encryption_envelope.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use agency_client::testing::mocking::AgencyMockDecrypted;
22
use aries_vcx_core::{global::settings::VERKEY, wallet::base_wallet::BaseWallet};
3-
use did_doc::schema::did_doc::DidDocument;
3+
use did_doc::schema::{did_doc::DidDocument, types::uri::Uri};
44
use diddoc_legacy::aries::diddoc::AriesDidDoc;
55
use messages::{
66
msg_fields::protocols::routing::{Forward, ForwardContent},
@@ -43,15 +43,28 @@ impl EncryptionEnvelope {
4343
Self::create_from_keys(wallet, data, sender_vk, recipient_key, routing_keys).await
4444
}
4545

46+
/// Create encrypted message based on key agreement keys of our did document, counterparties
47+
/// did document and their specific service, identified by id, which must be part of their
48+
/// did document
49+
///
50+
/// # Arguments
51+
///
52+
/// * `our_did_doc` - Our did_document, which the counterparty should already be in possession
53+
/// of
54+
/// * `their_did_doc` - The did document of the counterparty, the recipient of the encrypted
55+
/// message
56+
/// * `their_service_id` - Id of service where message will be sent. The counterparty did
57+
/// document must contain Service object identified with such value.
4658
pub async fn create(
4759
wallet: &impl BaseWallet,
4860
data: &[u8],
4961
our_did_doc: &DidDocument,
5062
their_did_doc: &DidDocument,
63+
their_service_id: &Uri,
5164
) -> VcxResult<EncryptionEnvelope> {
5265
let sender_vk = resolve_base58_key_agreement(our_did_doc)?;
5366
let recipient_key = resolve_base58_key_agreement(their_did_doc)?;
54-
let routing_keys = get_routing_keys(their_did_doc)?;
67+
let routing_keys = get_routing_keys(their_did_doc, their_service_id)?;
5568

5669
EncryptionEnvelope::create_from_keys(
5770
wallet,

aries/aries_vcx/tests/test_did_exchange.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ use aries_vcx::{
1818
};
1919
use aries_vcx_core::ledger::indy_vdr_ledger::DefaultIndyLedgerRead;
2020
use did_doc::schema::{
21-
did_doc::DidDocument, service::typed::didcommv1::ServiceDidCommV1, types::uri::Uri,
21+
did_doc::DidDocument,
22+
service::typed::{didcommv1::ServiceDidCommV1, ServiceType},
23+
types::uri::Uri,
2224
};
2325
use did_parser::Did;
2426
use did_peer::{
@@ -179,11 +181,15 @@ async fn did_exchange_test() -> Result<(), Box<dyn Error>> {
179181
);
180182

181183
let data = "Hello world";
184+
let service = requester
185+
.their_did_doc()
186+
.get_service_of_type(&ServiceType::DIDCommV1)?;
182187
let m = EncryptionEnvelope::create(
183188
&agent_invitee.wallet,
184189
data.as_bytes(),
185190
requester.our_did_doc(),
186191
requester.their_did_doc(),
192+
service.id(),
187193
)
188194
.await?;
189195

aries/misc/shared/src/http_client.rs

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ lazy_static! {
2121
};
2222
}
2323

24+
// todo: take Url by reference
2425
pub async fn post_message(body_content: Vec<u8>, url: Url) -> HttpResult<Vec<u8>> {
2526
debug!("post_message >> http client sending request POST {}", &url);
2627

did_core/did_doc/src/schema/service/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ impl Service {
4747
&self.id
4848
}
4949

50+
pub fn contains_service_type(&self, tested_service_type: &ServiceType) -> bool {
51+
match &self.service_type {
52+
OneOrList::One(service_type) => tested_service_type == service_type,
53+
OneOrList::List(service_types) => service_types.contains(tested_service_type),
54+
}
55+
}
56+
5057
pub fn service_type(&self) -> &OneOrList<ServiceType> {
5158
&self.service_type
5259
}

did_core/did_doc/src/schema/utils/mod.rs

+32-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use crate::{
66
error::DidDocumentBuilderError,
77
schema::{
88
did_doc::DidDocument,
9+
service::{typed::ServiceType, Service},
10+
types::uri::Uri,
911
verification_method::{VerificationMethod, VerificationMethodKind, VerificationMethodType},
1012
},
1113
};
@@ -36,7 +38,7 @@ impl<T: Display + Debug> Display for OneOrList<T> {
3638
}
3739

3840
impl DidDocument {
39-
pub fn find_key_agreement_of_type(
41+
pub fn get_key_agreement_of_type(
4042
&self,
4143
key_types: &[VerificationMethodType],
4244
) -> Result<VerificationMethod, DidDocumentBuilderError> {
@@ -65,6 +67,33 @@ impl DidDocument {
6567
"No supported key_agreement keys have been found".to_string(),
6668
))
6769
}
70+
71+
pub fn get_service_of_type(
72+
&self,
73+
service_type: &ServiceType,
74+
) -> Result<Service, DidDocumentBuilderError> {
75+
for service in self.service() {
76+
if service.contains_service_type(service_type) {
77+
return Ok(service.clone());
78+
}
79+
}
80+
Err(DidDocumentBuilderError::CustomError(format!(
81+
"No service of type {}",
82+
service_type
83+
)))
84+
}
85+
86+
pub fn get_service_by_id(&self, id: &Uri) -> Result<Service, DidDocumentBuilderError> {
87+
for service in self.service() {
88+
if service.id() == id {
89+
return Ok(service.clone());
90+
}
91+
}
92+
Err(DidDocumentBuilderError::CustomError(format!(
93+
"No service found by id {}",
94+
id
95+
)))
96+
}
6897
}
6998

7099
#[cfg(test)]
@@ -106,7 +135,7 @@ mod tests {
106135
VerificationMethodType::Ed25519VerificationKey2020,
107136
VerificationMethodType::X25519KeyAgreementKey2020,
108137
];
109-
let key = did_document.find_key_agreement_of_type(methods).unwrap();
138+
let key = did_document.get_key_agreement_of_type(methods).unwrap();
110139
assert_eq!(key.id().to_string(), "#bar")
111140
}
112141

@@ -115,7 +144,7 @@ mod tests {
115144
let did_document: DidDocument = serde_json::from_str(DID_DOC).unwrap();
116145
let methods = &vec![VerificationMethodType::Bls12381G1Key2020];
117146
let err = did_document
118-
.find_key_agreement_of_type(methods)
147+
.get_key_agreement_of_type(methods)
119148
.expect_err("expected error");
120149
assert!(err
121150
.to_string()

0 commit comments

Comments
 (0)