Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: encryption envelope #1070

Merged
merged 4 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.

69 changes: 37 additions & 32 deletions aries/aries_vcx/src/utils/encryption_envelope.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use agency_client::testing::mocking::AgencyMockDecrypted;
use aries_vcx_core::{global::settings::VERKEY, wallet::base_wallet::BaseWallet};
use diddoc_legacy::aries::diddoc::AriesDidDoc;
use futures::TryFutureExt;
use messages::{
msg_fields::protocols::routing::{Forward, ForwardContent},
AriesMessage,
Expand All @@ -19,63 +18,69 @@ impl EncryptionEnvelope {
pub async fn create(
wallet: &impl BaseWallet,
message: &[u8],
pw_verkey: Option<&str>,
sender_vk: Option<&str>,
did_doc: &AriesDidDoc,
) -> VcxResult<EncryptionEnvelope> {
trace!(
"EncryptionEnvelope::create >>> message: {:?}, pw_verkey: {:?}, did_doc: {:?}",
message,
pw_verkey,
sender_vk,
did_doc
);

EncryptionEnvelope::encrypt_for_pairwise(wallet, message, pw_verkey, did_doc)
.and_then(|message| async move {
EncryptionEnvelope::wrap_into_forward_messages(wallet, message, did_doc).await
})
.await
.map(EncryptionEnvelope)
let recipient_keys = json!(did_doc.recipient_keys()?).to_string();
let routing_keys = did_doc.routing_keys();
let message = EncryptionEnvelope::encrypt_for_pairwise(
wallet,
message,
sender_vk,
recipient_keys.clone(),
)
.await?;
EncryptionEnvelope::wrap_into_forward_messages(
wallet,
message,
recipient_keys,
routing_keys,
)
.await
.map(EncryptionEnvelope)
}

async fn encrypt_for_pairwise(
wallet: &impl BaseWallet,
message: &[u8],
pw_verkey: Option<&str>,
did_doc: &AriesDidDoc,
sender_vk: Option<&str>,
recipient_key: String,
) -> VcxResult<Vec<u8>> {
let receiver_keys = json!(did_doc.recipient_keys()?).to_string();

debug!(
"Encrypting for pairwise; pw_verkey: {:?}, receiver_keys: {:?}",
pw_verkey, receiver_keys
"Encrypting for pairwise; sender_vk: {:?}, recipient_key: {}",
sender_vk, recipient_key
);

wallet
.pack_message(pw_verkey, &receiver_keys, message)
.pack_message(sender_vk, &recipient_key, message)
.await
.map_err(|err| err.into())
}

async fn wrap_into_forward_messages(
wallet: &impl BaseWallet,
mut message: Vec<u8>,
did_doc: &AriesDidDoc,
recipient_key: String,
routing_keys: Vec<String>,
) -> VcxResult<Vec<u8>> {
let recipient_keys = did_doc.recipient_keys()?;
let routing_keys = did_doc.routing_keys();

let mut to = recipient_keys
.get(0)
.map(String::from)
.ok_or(AriesVcxError::from_msg(
AriesVcxErrorKind::InvalidState,
format!("Recipient Key not found in DIDDoc: {:?}", did_doc),
))?;
let mut forward_to_key = recipient_key.clone();

for routing_key in routing_keys.iter() {
message =
EncryptionEnvelope::wrap_into_forward(wallet, message, &to, routing_key).await?;
to = routing_key.clone();
message = EncryptionEnvelope::wrap_into_forward(
wallet,
message,
&forward_to_key,
routing_key,
)
.await?;
forward_to_key = routing_key.clone();
}

Ok(message)
Expand All @@ -84,11 +89,11 @@ impl EncryptionEnvelope {
async fn wrap_into_forward(
wallet: &impl BaseWallet,
message: Vec<u8>,
to: &str,
forward_to_key: &str,
routing_key: &str,
) -> VcxResult<Vec<u8>> {
let content = ForwardContent::builder()
.to(to.to_string())
.to(forward_to_key.to_string())
.msg(serde_json::from_slice(&message)?)
.build();

Expand Down
1 change: 1 addition & 0 deletions aries/messages/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ diddoc_legacy = { path = "../misc/legacy/diddoc_legacy" }
shared = { path = "../misc/shared" }
did_parser = { path = "../../did_core/did_parser" }
did_doc_sov = { path = "../../did_core/did_doc_sov" }
display_as_json = { path = "../../misc/display_as_json" }
15 changes: 14 additions & 1 deletion aries/messages/src/msg_fields/protocols/did_exchange/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ mod tests {
timing::tests::make_extended_timing,
},
misc::test_utils,
msg_fields::protocols::did_exchange::request::{Request, RequestDecorators},
msg_types::protocols::did_exchange::DidExchangeTypeV1_0,
};

fn request_content() -> RequestContent {
pub fn request_content() -> RequestContent {
let did_doc = AriesDidDoc::default();
RequestContent {
label: "test_request_label".to_owned(),
Expand All @@ -73,6 +74,18 @@ mod tests {
}
}

#[test]
fn test_print_message() {
let msg: Request = Request::builder()
.id("test_id".to_owned())
.content(request_content())
.decorators(RequestDecorators::default())
.build();
let printed_json = format!("{}", msg);
let parsed_request: Request = serde_json::from_str(&printed_json).unwrap();
assert_eq!(msg, parsed_request);
}

#[test]
fn test_minimal_didexchange_request() {
let content = request_content();
Expand Down
4 changes: 2 additions & 2 deletions aries/messages/src/msg_parts.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use display_as_json::Display;
use serde::{Deserialize, Serialize};
// Bind `shared::misc::serde_ignored::SerdeIgnored` type as `NoDecorators`.
use shared::misc::serde_ignored::SerdeIgnored as NoDecorators;
use typed_builder::TypedBuilder;

Expand All @@ -14,7 +14,7 @@ use typed_builder::TypedBuilder;
/// `~attach` used in some messages that are in fact part of the protocol itself and are
/// instrumental to the message processing, not an appendix to the message (such as `~thread` or
/// `~timing`).
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, TypedBuilder)]
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, TypedBuilder, Display)]
#[builder(build_method(vis = "", name = __build))]
pub struct MsgParts<C, D = NoDecorators> {
/// All standalone messages have an `id` field.
Expand Down
34 changes: 29 additions & 5 deletions misc/display_as_json/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,37 @@ pub fn display_as_json_derive(input: TokenStream) -> TokenStream {

fn impl_display(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
let generics = &ast.generics;

let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

// For each of the generics parameter G, we prepare addition trait bound "G: serde::Serialize"
let serialize_bounds = generics.params.iter().filter_map(|param| {
match param {
syn::GenericParam::Type(type_param) => {
let ident = &type_param.ident;
Some(quote! { #ident: serde::Serialize })
}
_ => None, // Skip non-type parameters, eg lifetimes
}
});

// Combine the original where clause with additional bounds we prepared above
// See quote! macro docs for more info on the #() syntax https://docs.rs/quote/1.0.33/quote/macro.quote.html
let combined_where_clause = if where_clause.is_none() {
quote! { where #(#serialize_bounds),* }
} else {
quote! { #where_clause, #(#serialize_bounds),* }
};

// Generate the actual impl
let gen = quote! {
impl std::fmt::Display for #name {
impl #impl_generics std::fmt::Display for #name #ty_generics #combined_where_clause {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let json = serde_json::to_string(self).unwrap_or_else(|e| {
format!("Error serializing {}: {}", stringify!(#name), e)
});
write!(f, "{}", json)
match serde_json::to_string(self) {
Ok(json) => write!(f, "{}", json),
Err(e) => write!(f, "Error serializing {}: {}", stringify!(#name), e),
}
}
}
};
Expand Down
Loading