From f667d1bd9d85f36d3b5c4a12708d1d508c0cddfc Mon Sep 17 00:00:00 2001 From: James Ebert Date: Wed, 7 Aug 2024 23:57:24 -0700 Subject: [PATCH 01/10] feat: added invitation parsing from json, base64url, and url Signed-off-by: James Ebert --- aries/aries_vcx/src/errors/mapping_others.rs | 22 +++++++- .../src/handlers/out_of_band/receiver.rs | 53 ++++++++++++++++--- 2 files changed, 68 insertions(+), 7 deletions(-) diff --git a/aries/aries_vcx/src/errors/mapping_others.rs b/aries/aries_vcx/src/errors/mapping_others.rs index b58b243a86..8709c69450 100644 --- a/aries/aries_vcx/src/errors/mapping_others.rs +++ b/aries/aries_vcx/src/errors/mapping_others.rs @@ -1,7 +1,9 @@ -use std::{num::ParseIntError, sync::PoisonError}; +use std::{num::ParseIntError, string::FromUtf8Error, sync::PoisonError}; +use base64::DecodeError; use did_doc::schema::{types::uri::UriWrapperError, utils::error::DidDocumentLookupError}; use shared::errors::http_error::HttpError; +use url::ParseError; use crate::{ errors::error::{AriesVcxError, AriesVcxErrorKind}, @@ -92,3 +94,21 @@ impl From for AriesVcxError { AriesVcxError::from_msg(AriesVcxErrorKind::InvalidInput, err.to_string()) } } + +impl From for AriesVcxError { + fn from(err: DecodeError) -> Self { + AriesVcxError::from_msg(AriesVcxErrorKind::InvalidInput, err.to_string()) + } +} + +impl From for AriesVcxError { + fn from(err: FromUtf8Error) -> Self { + AriesVcxError::from_msg(AriesVcxErrorKind::InvalidInput, err.to_string()) + } +} + +impl From for AriesVcxError { + fn from(err: ParseError) -> Self { + AriesVcxError::from_msg(AriesVcxErrorKind::InvalidInput, err.to_string()) + } +} diff --git a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs index 6e19fe7914..a7118b3fec 100644 --- a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs +++ b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs @@ -12,8 +12,11 @@ use messages::{ }; use serde::Deserialize; use serde_json::Value; +use url::Url; -use crate::{errors::error::prelude::*, handlers::util::AttachmentId}; +use crate::{ + errors::error::prelude::*, handlers::util::AttachmentId, utils::base64::URL_SAFE_LENIENT, +}; #[derive(Debug, PartialEq, Clone)] pub struct OutOfBandReceiver { @@ -38,6 +41,25 @@ impl OutOfBandReceiver { } } + pub fn from_json_string(oob_json: &str) -> VcxResult { + Ok(Self { + oob: from_json_string(oob_json)?, + }) + } + + pub fn from_base64_url(base64_url_encoded_oob: &str) -> VcxResult { + Ok(Self { + oob: from_json_string(&from_base64_url(base64_url_encoded_oob)?)?, + }) + } + + pub fn from_url(oob_url_string: &str) -> VcxResult { + // TODO - URL Shortening + Ok(Self { + oob: from_json_string(&from_base64_url(&from_url(oob_url_string)?)?)?, + }) + } + pub fn get_id(&self) -> String { self.oob.id.clone() } @@ -61,12 +83,31 @@ impl OutOfBandReceiver { pub fn to_aries_message(&self) -> AriesMessage { self.oob.clone().into() } +} - pub fn from_string(oob_data: &str) -> VcxResult { - Ok(Self { - oob: serde_json::from_str(oob_data)?, - }) - } +fn from_json_string(oob_json: &str) -> VcxResult { + Ok(serde_json::from_str(oob_json)?) +} + +fn from_base64_url(base64_url_encoded_oob: &str) -> VcxResult { + Ok(String::from_utf8( + URL_SAFE_LENIENT.decode(base64_url_encoded_oob)?, + )?) +} + +fn from_url(oob_url_string: &str) -> VcxResult { + let oob_url = Url::parse(oob_url_string)?; + let (_oob_query, base64_url_encoded_oob) = oob_url + .query_pairs() + .find(|(name, _value)| name == &"oob") + .ok_or_else(|| { + AriesVcxError::from_msg( + AriesVcxErrorKind::InvalidInput, + "OutOfBand Invitation URL is missing 'oob' query parameter", + ) + })?; + + Ok(base64_url_encoded_oob.into_owned()) } impl Display for OutOfBandReceiver { From f188156efc752d8ef042329b9dfec089b347028e Mon Sep 17 00:00:00 2001 From: James Ebert Date: Thu, 8 Aug 2024 00:19:56 -0700 Subject: [PATCH 02/10] feat: added invitation to json, base64url, and url Signed-off-by: James Ebert --- .../src/handlers/out_of_band/receiver.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs index a7118b3fec..3231f3a3a0 100644 --- a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs +++ b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs @@ -83,6 +83,21 @@ impl OutOfBandReceiver { pub fn to_aries_message(&self) -> AriesMessage { self.oob.clone().into() } + + pub fn to_json_string(&self) -> VcxResult { + Ok(serde_json::to_string(&self.oob)?) + } + + pub fn to_base64_url(&self) -> String { + URL_SAFE_LENIENT.encode(self.oob.to_string()) + } + + pub fn to_url(&self, domain_path: &str) -> VcxResult { + let mut oob_url = Url::parse(&(domain_path.to_owned() + &self.oob.to_string()))?; + let oob_query = "oob=".to_owned() + &self.to_base64_url(); + oob_url.set_query(Some(&oob_query)); + Ok(oob_url) + } } fn from_json_string(oob_json: &str) -> VcxResult { From d9766dbc5c6161509cdcad7f96167c132b1f58a5 Mon Sep 17 00:00:00 2001 From: James Ebert Date: Thu, 8 Aug 2024 01:39:43 -0700 Subject: [PATCH 03/10] feat: add tests, fix minor output issues Signed-off-by: James Ebert --- .../src/handlers/out_of_band/receiver.rs | 139 +++++++++++++++++- 1 file changed, 134 insertions(+), 5 deletions(-) diff --git a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs index 3231f3a3a0..d581572a31 100644 --- a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs +++ b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs @@ -1,6 +1,6 @@ use std::{clone::Clone, fmt::Display, str::FromStr}; -use base64::{engine::general_purpose, Engine}; +use base64::{engine::general_purpose, prelude::BASE64_URL_SAFE, Engine}; use messages::{ decorators::attachment::{Attachment, AttachmentType}, msg_fields::protocols::{ @@ -84,16 +84,16 @@ impl OutOfBandReceiver { self.oob.clone().into() } - pub fn to_json_string(&self) -> VcxResult { - Ok(serde_json::to_string(&self.oob)?) + pub fn to_json_string(&self) -> String { + self.to_aries_message().to_string() } pub fn to_base64_url(&self) -> String { - URL_SAFE_LENIENT.encode(self.oob.to_string()) + BASE64_URL_SAFE.encode(self.to_json_string()) } pub fn to_url(&self, domain_path: &str) -> VcxResult { - let mut oob_url = Url::parse(&(domain_path.to_owned() + &self.oob.to_string()))?; + let mut oob_url = Url::parse(&domain_path.to_owned())?; let oob_query = "oob=".to_owned() + &self.to_base64_url(); oob_url.set_query(Some(&oob_query)); Ok(oob_url) @@ -192,3 +192,132 @@ fn attachment_to_aries_message(attach: &Attachment) -> VcxResult Invitation { + let id = "69212a3a-d068-4f9d-a2dd-4741bca89af3"; + let did = "did:sov:LjgpST2rjsoxYegQDRm7EL"; + let service = OobService::Did(did.to_string()); + let handshake_protocols = vec![ + MaybeKnown::Known(Protocol::DidExchangeType(DidExchangeType::V1( + DidExchangeTypeV1::new_v1_0(), + ))), + MaybeKnown::Known(Protocol::ConnectionType(ConnectionType::V1( + ConnectionTypeV1::new_v1_0(), + ))), + ]; + let content = InvitationContent::builder() + .services(vec![service]) + .goal("To issue a Faber College Graduate credential".to_string()) + .goal_code(MaybeKnown::Known(OobGoalCode::IssueVC)) + .label("Faber College".to_string()) + .handshake_protocols(handshake_protocols) + .build(); + let decorators = InvitationDecorators::default(); + + let invitation: Invitation = Invitation::builder() + .id(id.to_string()) + .content(content) + .decorators(decorators) + .build(); + + invitation + } + + #[test] + fn receive_invitation_by_json() { + let base_invite = _create_invitation(); + let parsed_invite = OutOfBandReceiver::from_json_string(JSON_OOB_INVITE) + .unwrap() + .oob; + assert_eq!(base_invite, parsed_invite); + } + + #[test] + fn receive_invitation_by_json_no_whitespace() { + let base_invite = _create_invitation(); + let parsed_invite = OutOfBandReceiver::from_json_string(JSON_OOB_INVITE_NO_WHITESPACE) + .unwrap() + .oob; + assert_eq!(base_invite, parsed_invite); + } + + #[test] + fn receive_invitation_by_base64_url() { + let base_invite = _create_invitation(); + let parsed_invite = OutOfBandReceiver::from_base64_url(OOB_BASE64_URL_ENCODED) + .unwrap() + .oob; + assert_eq!(base_invite, parsed_invite); + } + + #[test] + fn receive_invitation_by_url() { + let base_invite = _create_invitation(); + let parsed_invite = OutOfBandReceiver::from_url(OOB_URL).unwrap().oob; + assert_eq!(base_invite, parsed_invite); + } + + #[test] + fn invitation_to_json() { + let out_of_band_receiver = OutOfBandReceiver::from_json_string(JSON_OOB_INVITE).unwrap(); + + let json_invite = out_of_band_receiver.to_json_string(); + + assert_eq!(JSON_OOB_INVITE_NO_WHITESPACE, json_invite); + } + + #[test] + fn invitation_to_base64_url() { + let out_of_band_receiver = OutOfBandReceiver::from_json_string(JSON_OOB_INVITE).unwrap(); + + let base64_url_invite = out_of_band_receiver.to_base64_url(); + + assert_eq!(OOB_BASE64_URL_ENCODED, base64_url_invite); + } + + #[test] + fn invitation_to_url() { + let out_of_band_receiver = OutOfBandReceiver::from_json_string(JSON_OOB_INVITE).unwrap(); + + let oob_url = out_of_band_receiver + .to_url("http://example.com/ssi") + .unwrap() + .to_string(); + + assert_eq!(OOB_URL, oob_url); + } +} From 6717eb8943f3b73ff8a54ff9c754fa82a8e1a661 Mon Sep 17 00:00:00 2001 From: James Ebert Date: Thu, 8 Aug 2024 01:53:59 -0700 Subject: [PATCH 04/10] feat: added additional formats to outofbandsender, added tests Signed-off-by: James Ebert --- .../src/handlers/out_of_band/receiver.rs | 5 +- .../src/handlers/out_of_band/sender.rs | 106 +++++++++++++++++- 2 files changed, 103 insertions(+), 8 deletions(-) diff --git a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs index d581572a31..c32233ca26 100644 --- a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs +++ b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs @@ -195,6 +195,7 @@ fn attachment_to_aries_message(attach: &Attachment) -> VcxResult Self { + Self { oob: invitation } + } + pub fn set_label(mut self, label: &str) -> Self { self.oob.content.label = Some(label.to_string()); self @@ -128,10 +134,19 @@ impl OutOfBandSender { self.oob.clone().into() } - pub fn from_string(oob_data: &str) -> VcxResult { - Ok(Self { - oob: serde_json::from_str(oob_data)?, - }) + pub fn to_json_string(&self) -> String { + self.to_aries_message().to_string() + } + + pub fn to_base64_url(&self) -> String { + BASE64_URL_SAFE.encode(self.to_json_string()) + } + + pub fn to_url(&self, domain_path: &str) -> VcxResult { + let mut oob_url = Url::parse(&domain_path.to_owned())?; + let oob_query = "oob=".to_owned() + &self.to_base64_url(); + oob_url.set_query(Some(&oob_query)); + Ok(oob_url) } } @@ -141,6 +156,89 @@ impl Display for OutOfBandSender { } } +#[cfg(test)] +mod tests { + use super::*; + use messages::{ + msg_fields::protocols::out_of_band::{ + invitation::{Invitation, InvitationContent, InvitationDecorators, OobService}, + OobGoalCode, + }, + msg_types::{ + connection::{ConnectionType, ConnectionTypeV1}, + protocols::did_exchange::{DidExchangeType, DidExchangeTypeV1}, + Protocol, + }, + }; + use shared::maybe_known::MaybeKnown; + + // Example invite formats referenced (with change to use OOB 1.1) from example invite in RFC 0434 - https://github.com/hyperledger/aries-rfcs/tree/main/features/0434-outofband + const JSON_OOB_INVITE_NO_WHITESPACE: &str = r#"{"@type":"https://didcomm.org/out-of-band/1.1/invitation","@id":"69212a3a-d068-4f9d-a2dd-4741bca89af3","label":"Faber College","goal_code":"issue-vc","goal":"To issue a Faber College Graduate credential","handshake_protocols":["https://didcomm.org/didexchange/1.0","https://didcomm.org/connections/1.0"],"services":["did:sov:LjgpST2rjsoxYegQDRm7EL"]}"#; + const OOB_BASE64_URL_ENCODED: &str = "eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0="; + const OOB_URL: &str = "http://example.com/ssi?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0="; + + // Params mimic example invitation in RFC 0434 - https://github.com/hyperledger/aries-rfcs/tree/main/features/0434-outofband + fn _create_invitation() -> Invitation { + let id = "69212a3a-d068-4f9d-a2dd-4741bca89af3"; + let did = "did:sov:LjgpST2rjsoxYegQDRm7EL"; + let service = OobService::Did(did.to_string()); + let handshake_protocols = vec![ + MaybeKnown::Known(Protocol::DidExchangeType(DidExchangeType::V1( + DidExchangeTypeV1::new_v1_0(), + ))), + MaybeKnown::Known(Protocol::ConnectionType(ConnectionType::V1( + ConnectionTypeV1::new_v1_0(), + ))), + ]; + let content = InvitationContent::builder() + .services(vec![service]) + .goal("To issue a Faber College Graduate credential".to_string()) + .goal_code(MaybeKnown::Known(OobGoalCode::IssueVC)) + .label("Faber College".to_string()) + .handshake_protocols(handshake_protocols) + .build(); + let decorators = InvitationDecorators::default(); + + let invitation: Invitation = Invitation::builder() + .id(id.to_string()) + .content(content) + .decorators(decorators) + .build(); + + invitation + } + + #[test] + fn invitation_to_json() { + let out_of_band_sender = OutOfBandSender::create_from_invitation(_create_invitation()); + + let json_invite = out_of_band_sender.to_json_string(); + + assert_eq!(JSON_OOB_INVITE_NO_WHITESPACE, json_invite); + } + + #[test] + fn invitation_to_base64_url() { + let out_of_band_sender = OutOfBandSender::create_from_invitation(_create_invitation()); + + let base64_url_invite = out_of_band_sender.to_base64_url(); + + assert_eq!(OOB_BASE64_URL_ENCODED, base64_url_invite); + } + + #[test] + fn invitation_to_url() { + let out_of_band_sender = OutOfBandSender::create_from_invitation(_create_invitation()); + + let oob_url = out_of_band_sender + .to_url("http://example.com/ssi") + .unwrap() + .to_string(); + + assert_eq!(OOB_URL, oob_url); + } +} + // #[cfg(test)] // mod unit_tests { // use crate::utils::devsetup::SetupMocks; From 7e3c94ad5de870ee3315f4857cbee1211bedf05a Mon Sep 17 00:00:00 2001 From: James Ebert Date: Thu, 8 Aug 2024 02:09:29 -0700 Subject: [PATCH 05/10] chore: fix formatting/clippy Signed-off-by: James Ebert --- aries/aries_vcx/src/handlers/out_of_band/receiver.rs | 7 ++++--- aries/aries_vcx/src/handlers/out_of_band/sender.rs | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs index c32233ca26..466efa021f 100644 --- a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs +++ b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs @@ -93,7 +93,7 @@ impl OutOfBandReceiver { } pub fn to_url(&self, domain_path: &str) -> VcxResult { - let mut oob_url = Url::parse(&domain_path.to_owned())?; + let mut oob_url = Url::parse(&domain_path)?; let oob_query = "oob=".to_owned() + &self.to_base64_url(); oob_url.set_query(Some(&oob_query)); Ok(oob_url) @@ -114,7 +114,7 @@ fn from_url(oob_url_string: &str) -> VcxResult { let oob_url = Url::parse(oob_url_string)?; let (_oob_query, base64_url_encoded_oob) = oob_url .query_pairs() - .find(|(name, _value)| name == &"oob") + .find(|(name, _value)| name == "oob") .ok_or_else(|| { AriesVcxError::from_msg( AriesVcxErrorKind::InvalidInput, @@ -195,7 +195,6 @@ fn attachment_to_aries_message(attach: &Attachment) -> VcxResult VcxResult { - let mut oob_url = Url::parse(&domain_path.to_owned())?; + let mut oob_url = Url::parse(&domain_path)?; let oob_query = "oob=".to_owned() + &self.to_base64_url(); oob_url.set_query(Some(&oob_query)); Ok(oob_url) @@ -158,7 +158,6 @@ impl Display for OutOfBandSender { #[cfg(test)] mod tests { - use super::*; use messages::{ msg_fields::protocols::out_of_band::{ invitation::{Invitation, InvitationContent, InvitationDecorators, OobService}, @@ -172,6 +171,8 @@ mod tests { }; use shared::maybe_known::MaybeKnown; + use super::*; + // Example invite formats referenced (with change to use OOB 1.1) from example invite in RFC 0434 - https://github.com/hyperledger/aries-rfcs/tree/main/features/0434-outofband const JSON_OOB_INVITE_NO_WHITESPACE: &str = r#"{"@type":"https://didcomm.org/out-of-band/1.1/invitation","@id":"69212a3a-d068-4f9d-a2dd-4741bca89af3","label":"Faber College","goal_code":"issue-vc","goal":"To issue a Faber College Graduate credential","handshake_protocols":["https://didcomm.org/didexchange/1.0","https://didcomm.org/connections/1.0"],"services":["did:sov:LjgpST2rjsoxYegQDRm7EL"]}"#; const OOB_BASE64_URL_ENCODED: &str = "eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0="; From c979948d5dd2deea69312ddc7647da0f9e3d3e53 Mon Sep 17 00:00:00 2001 From: James Ebert Date: Thu, 8 Aug 2024 02:12:58 -0700 Subject: [PATCH 06/10] chore: fix clippy issue Signed-off-by: James Ebert --- aries/aries_vcx/src/handlers/out_of_band/receiver.rs | 2 +- aries/aries_vcx/src/handlers/out_of_band/sender.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs index 466efa021f..77b5ea23b8 100644 --- a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs +++ b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs @@ -93,7 +93,7 @@ impl OutOfBandReceiver { } pub fn to_url(&self, domain_path: &str) -> VcxResult { - let mut oob_url = Url::parse(&domain_path)?; + let mut oob_url = Url::parse(domain_path)?; let oob_query = "oob=".to_owned() + &self.to_base64_url(); oob_url.set_query(Some(&oob_query)); Ok(oob_url) diff --git a/aries/aries_vcx/src/handlers/out_of_band/sender.rs b/aries/aries_vcx/src/handlers/out_of_band/sender.rs index 17e4a6bb78..bbb43af22c 100644 --- a/aries/aries_vcx/src/handlers/out_of_band/sender.rs +++ b/aries/aries_vcx/src/handlers/out_of_band/sender.rs @@ -143,7 +143,7 @@ impl OutOfBandSender { } pub fn to_url(&self, domain_path: &str) -> VcxResult { - let mut oob_url = Url::parse(&domain_path)?; + let mut oob_url = Url::parse(domain_path)?; let oob_query = "oob=".to_owned() + &self.to_base64_url(); oob_url.set_query(Some(&oob_query)); Ok(oob_url) From 042617d792f1432b7883be6744242e7b774fd4fa Mon Sep 17 00:00:00 2001 From: James Ebert Date: Thu, 8 Aug 2024 19:01:23 -0700 Subject: [PATCH 07/10] chore: adjust function/method names, added no invitation padding parsing test Signed-off-by: James Ebert --- .../src/handlers/out_of_band.rs | 2 +- .../src/handlers/out_of_band/receiver.rs | 85 ++++++++++++------- .../src/handlers/out_of_band/sender.rs | 20 ++--- 3 files changed, 66 insertions(+), 41 deletions(-) diff --git a/aries/agents/aries-vcx-agent/src/handlers/out_of_band.rs b/aries/agents/aries-vcx-agent/src/handlers/out_of_band.rs index 6d01745a55..9aa8558fe7 100644 --- a/aries/agents/aries-vcx-agent/src/handlers/out_of_band.rs +++ b/aries/agents/aries-vcx-agent/src/handlers/out_of_band.rs @@ -52,7 +52,7 @@ impl ServiceOutOfBand { GenericOutOfBand::Sender(sender.to_owned()), )?; - Ok(sender.to_aries_message()) + Ok(sender.invitation_to_aries_message()) } pub fn receive_invitation(&self, invitation: AriesMessage) -> AgentResult { diff --git a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs index 77b5ea23b8..6ae138f57e 100644 --- a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs +++ b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs @@ -41,22 +41,28 @@ impl OutOfBandReceiver { } } - pub fn from_json_string(oob_json: &str) -> VcxResult { + pub fn create_from_json_encoded_oob(oob_json: &str) -> VcxResult { Ok(Self { - oob: from_json_string(oob_json)?, + oob: extract_encoded_invitation_from_json_string(oob_json)?, }) } - pub fn from_base64_url(base64_url_encoded_oob: &str) -> VcxResult { + fn create_from_base64_url_encoded_oob(base64_url_encoded_oob: &str) -> VcxResult { Ok(Self { - oob: from_json_string(&from_base64_url(base64_url_encoded_oob)?)?, + oob: extract_encoded_invitation_from_json_string( + &extract_encoded_invitation_from_base64_url(base64_url_encoded_oob)?, + )?, }) } - pub fn from_url(oob_url_string: &str) -> VcxResult { + pub fn create_from_url_encoded_oob(oob_url_string: &str) -> VcxResult { // TODO - URL Shortening Ok(Self { - oob: from_json_string(&from_base64_url(&from_url(oob_url_string)?)?)?, + oob: extract_encoded_invitation_from_json_string( + &extract_encoded_invitation_from_base64_url(&extract_encoded_invitation_from_url( + oob_url_string, + )?)?, + )?, }) } @@ -80,37 +86,37 @@ impl OutOfBandReceiver { } } - pub fn to_aries_message(&self) -> AriesMessage { + pub fn invitation_to_aries_message(&self) -> AriesMessage { self.oob.clone().into() } - pub fn to_json_string(&self) -> String { - self.to_aries_message().to_string() + pub fn invitation_to_json_string(&self) -> String { + self.invitation_to_aries_message().to_string() } - pub fn to_base64_url(&self) -> String { - BASE64_URL_SAFE.encode(self.to_json_string()) + fn invitation_to_base64_url(&self) -> String { + BASE64_URL_SAFE.encode(self.invitation_to_json_string()) } - pub fn to_url(&self, domain_path: &str) -> VcxResult { + pub fn invitation_to_url(&self, domain_path: &str) -> VcxResult { let mut oob_url = Url::parse(domain_path)?; - let oob_query = "oob=".to_owned() + &self.to_base64_url(); + let oob_query = "oob=".to_owned() + &self.invitation_to_base64_url(); oob_url.set_query(Some(&oob_query)); Ok(oob_url) } } -fn from_json_string(oob_json: &str) -> VcxResult { +fn extract_encoded_invitation_from_json_string(oob_json: &str) -> VcxResult { Ok(serde_json::from_str(oob_json)?) } -fn from_base64_url(base64_url_encoded_oob: &str) -> VcxResult { +fn extract_encoded_invitation_from_base64_url(base64_url_encoded_oob: &str) -> VcxResult { Ok(String::from_utf8( URL_SAFE_LENIENT.decode(base64_url_encoded_oob)?, )?) } -fn from_url(oob_url_string: &str) -> VcxResult { +fn extract_encoded_invitation_from_url(oob_url_string: &str) -> VcxResult { let oob_url = Url::parse(oob_url_string)?; let (_oob_query, base64_url_encoded_oob) = oob_url .query_pairs() @@ -222,6 +228,7 @@ mod tests { }"#; const JSON_OOB_INVITE_NO_WHITESPACE: &str = r#"{"@type":"https://didcomm.org/out-of-band/1.1/invitation","@id":"69212a3a-d068-4f9d-a2dd-4741bca89af3","label":"Faber College","goal_code":"issue-vc","goal":"To issue a Faber College Graduate credential","handshake_protocols":["https://didcomm.org/didexchange/1.0","https://didcomm.org/connections/1.0"],"services":["did:sov:LjgpST2rjsoxYegQDRm7EL"]}"#; const OOB_BASE64_URL_ENCODED: &str = "eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0="; + const OOB_BASE64_URL_ENCODED_NO_PADDING: &str = "eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0"; const OOB_URL: &str = "http://example.com/ssi?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0="; // Params mimic example invitation in RFC 0434 - https://github.com/hyperledger/aries-rfcs/tree/main/features/0434-outofband @@ -258,7 +265,7 @@ mod tests { #[test] fn receive_invitation_by_json() { let base_invite = _create_invitation(); - let parsed_invite = OutOfBandReceiver::from_json_string(JSON_OOB_INVITE) + let parsed_invite = OutOfBandReceiver::create_from_json_encoded_oob(JSON_OOB_INVITE) .unwrap() .oob; assert_eq!(base_invite, parsed_invite); @@ -267,52 +274,70 @@ mod tests { #[test] fn receive_invitation_by_json_no_whitespace() { let base_invite = _create_invitation(); - let parsed_invite = OutOfBandReceiver::from_json_string(JSON_OOB_INVITE_NO_WHITESPACE) - .unwrap() - .oob; + let parsed_invite = + OutOfBandReceiver::create_from_json_encoded_oob(JSON_OOB_INVITE_NO_WHITESPACE) + .unwrap() + .oob; assert_eq!(base_invite, parsed_invite); } #[test] fn receive_invitation_by_base64_url() { let base_invite = _create_invitation(); - let parsed_invite = OutOfBandReceiver::from_base64_url(OOB_BASE64_URL_ENCODED) - .unwrap() - .oob; + let parsed_invite = + OutOfBandReceiver::create_from_base64_url_encoded_oob(OOB_BASE64_URL_ENCODED) + .unwrap() + .oob; + assert_eq!(base_invite, parsed_invite); + } + + #[test] + fn receive_invitation_by_base64_url_no_padding() { + let base_invite = _create_invitation(); + let parsed_invite = OutOfBandReceiver::create_from_base64_url_encoded_oob( + OOB_BASE64_URL_ENCODED_NO_PADDING, + ) + .unwrap() + .oob; assert_eq!(base_invite, parsed_invite); } #[test] fn receive_invitation_by_url() { let base_invite = _create_invitation(); - let parsed_invite = OutOfBandReceiver::from_url(OOB_URL).unwrap().oob; + let parsed_invite = OutOfBandReceiver::create_from_url_encoded_oob(OOB_URL) + .unwrap() + .oob; assert_eq!(base_invite, parsed_invite); } #[test] fn invitation_to_json() { - let out_of_band_receiver = OutOfBandReceiver::from_json_string(JSON_OOB_INVITE).unwrap(); + let out_of_band_receiver = + OutOfBandReceiver::create_from_json_encoded_oob(JSON_OOB_INVITE).unwrap(); - let json_invite = out_of_band_receiver.to_json_string(); + let json_invite = out_of_band_receiver.invitation_to_json_string(); assert_eq!(JSON_OOB_INVITE_NO_WHITESPACE, json_invite); } #[test] fn invitation_to_base64_url() { - let out_of_band_receiver = OutOfBandReceiver::from_json_string(JSON_OOB_INVITE).unwrap(); + let out_of_band_receiver = + OutOfBandReceiver::create_from_json_encoded_oob(JSON_OOB_INVITE).unwrap(); - let base64_url_invite = out_of_band_receiver.to_base64_url(); + let base64_url_invite = out_of_band_receiver.invitation_to_base64_url(); assert_eq!(OOB_BASE64_URL_ENCODED, base64_url_invite); } #[test] fn invitation_to_url() { - let out_of_band_receiver = OutOfBandReceiver::from_json_string(JSON_OOB_INVITE).unwrap(); + let out_of_band_receiver = + OutOfBandReceiver::create_from_json_encoded_oob(JSON_OOB_INVITE).unwrap(); let oob_url = out_of_band_receiver - .to_url("http://example.com/ssi") + .invitation_to_url("http://example.com/ssi") .unwrap() .to_string(); diff --git a/aries/aries_vcx/src/handlers/out_of_band/sender.rs b/aries/aries_vcx/src/handlers/out_of_band/sender.rs index bbb43af22c..a058c11ad2 100644 --- a/aries/aries_vcx/src/handlers/out_of_band/sender.rs +++ b/aries/aries_vcx/src/handlers/out_of_band/sender.rs @@ -130,21 +130,21 @@ impl OutOfBandSender { Ok(self) } - pub fn to_aries_message(&self) -> AriesMessage { + pub fn invitation_to_aries_message(&self) -> AriesMessage { self.oob.clone().into() } - pub fn to_json_string(&self) -> String { - self.to_aries_message().to_string() + pub fn invitation_to_json_string(&self) -> String { + self.invitation_to_aries_message().to_string() } - pub fn to_base64_url(&self) -> String { - BASE64_URL_SAFE.encode(self.to_json_string()) + fn invitation_to_base64_url(&self) -> String { + BASE64_URL_SAFE.encode(self.invitation_to_json_string()) } - pub fn to_url(&self, domain_path: &str) -> VcxResult { + pub fn invitation_to_url(&self, domain_path: &str) -> VcxResult { let mut oob_url = Url::parse(domain_path)?; - let oob_query = "oob=".to_owned() + &self.to_base64_url(); + let oob_query = "oob=".to_owned() + &self.invitation_to_base64_url(); oob_url.set_query(Some(&oob_query)); Ok(oob_url) } @@ -213,7 +213,7 @@ mod tests { fn invitation_to_json() { let out_of_band_sender = OutOfBandSender::create_from_invitation(_create_invitation()); - let json_invite = out_of_band_sender.to_json_string(); + let json_invite = out_of_band_sender.invitation_to_json_string(); assert_eq!(JSON_OOB_INVITE_NO_WHITESPACE, json_invite); } @@ -222,7 +222,7 @@ mod tests { fn invitation_to_base64_url() { let out_of_band_sender = OutOfBandSender::create_from_invitation(_create_invitation()); - let base64_url_invite = out_of_band_sender.to_base64_url(); + let base64_url_invite = out_of_band_sender.invitation_to_base64_url(); assert_eq!(OOB_BASE64_URL_ENCODED, base64_url_invite); } @@ -232,7 +232,7 @@ mod tests { let out_of_band_sender = OutOfBandSender::create_from_invitation(_create_invitation()); let oob_url = out_of_band_sender - .to_url("http://example.com/ssi") + .invitation_to_url("http://example.com/ssi") .unwrap() .to_string(); From 6f8fae921a903382f10a1734d14757dbd91e21ac Mon Sep 17 00:00:00 2001 From: James Ebert Date: Thu, 8 Aug 2024 19:28:12 -0700 Subject: [PATCH 08/10] chore: fix dead code needed by testing Signed-off-by: James Ebert --- aries/aries_vcx/src/handlers/out_of_band/receiver.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs index 6ae138f57e..61b48af560 100644 --- a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs +++ b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs @@ -47,6 +47,8 @@ impl OutOfBandReceiver { }) } + // This is here to help facilitate testing + #[allow(dead_code)] fn create_from_base64_url_encoded_oob(base64_url_encoded_oob: &str) -> VcxResult { Ok(Self { oob: extract_encoded_invitation_from_json_string( From f152f7ace9a9f4232badfb911af8676ddceb4d02 Mon Sep 17 00:00:00 2001 From: James Ebert Date: Sun, 18 Aug 2024 11:13:24 -0700 Subject: [PATCH 09/10] fix: adjust url encoding/parsing to account for percent-encoding urls Signed-off-by: James Ebert --- .../src/handlers/out_of_band/receiver.rs | 21 +++++++++++++++---- .../src/handlers/out_of_band/sender.rs | 10 +++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs index 61b48af560..7ba18851df 100644 --- a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs +++ b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs @@ -101,9 +101,11 @@ impl OutOfBandReceiver { } pub fn invitation_to_url(&self, domain_path: &str) -> VcxResult { - let mut oob_url = Url::parse(domain_path)?; - let oob_query = "oob=".to_owned() + &self.invitation_to_base64_url(); - oob_url.set_query(Some(&oob_query)); + let oob_url = Url::parse(domain_path)? + .query_pairs_mut() + .append_pair("oob", &self.invitation_to_base64_url()) + .finish() + .to_owned(); Ok(oob_url) } } @@ -231,7 +233,8 @@ mod tests { const JSON_OOB_INVITE_NO_WHITESPACE: &str = r#"{"@type":"https://didcomm.org/out-of-band/1.1/invitation","@id":"69212a3a-d068-4f9d-a2dd-4741bca89af3","label":"Faber College","goal_code":"issue-vc","goal":"To issue a Faber College Graduate credential","handshake_protocols":["https://didcomm.org/didexchange/1.0","https://didcomm.org/connections/1.0"],"services":["did:sov:LjgpST2rjsoxYegQDRm7EL"]}"#; const OOB_BASE64_URL_ENCODED: &str = "eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0="; const OOB_BASE64_URL_ENCODED_NO_PADDING: &str = "eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0"; - const OOB_URL: &str = "http://example.com/ssi?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0="; + const OOB_URL: &str = "http://example.com/ssi?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0%3D"; + const OOB_URL_NOT_PERCENT_ENCODED: &str = "http://example.com/ssi?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0="; // Params mimic example invitation in RFC 0434 - https://github.com/hyperledger/aries-rfcs/tree/main/features/0434-outofband fn _create_invitation() -> Invitation { @@ -313,6 +316,16 @@ mod tests { assert_eq!(base_invite, parsed_invite); } + #[test] + fn receive_invitation_by_url_no_percent_encoding() { + let base_invite = _create_invitation(); + let parsed_invite = + OutOfBandReceiver::create_from_url_encoded_oob(OOB_URL_NOT_PERCENT_ENCODED) + .unwrap() + .oob; + assert_eq!(base_invite, parsed_invite); + } + #[test] fn invitation_to_json() { let out_of_band_receiver = diff --git a/aries/aries_vcx/src/handlers/out_of_band/sender.rs b/aries/aries_vcx/src/handlers/out_of_band/sender.rs index a058c11ad2..4e9dec96bf 100644 --- a/aries/aries_vcx/src/handlers/out_of_band/sender.rs +++ b/aries/aries_vcx/src/handlers/out_of_band/sender.rs @@ -143,9 +143,11 @@ impl OutOfBandSender { } pub fn invitation_to_url(&self, domain_path: &str) -> VcxResult { - let mut oob_url = Url::parse(domain_path)?; - let oob_query = "oob=".to_owned() + &self.invitation_to_base64_url(); - oob_url.set_query(Some(&oob_query)); + let oob_url = Url::parse(domain_path)? + .query_pairs_mut() + .append_pair("oob", &self.invitation_to_base64_url()) + .finish() + .to_owned(); Ok(oob_url) } } @@ -176,7 +178,7 @@ mod tests { // Example invite formats referenced (with change to use OOB 1.1) from example invite in RFC 0434 - https://github.com/hyperledger/aries-rfcs/tree/main/features/0434-outofband const JSON_OOB_INVITE_NO_WHITESPACE: &str = r#"{"@type":"https://didcomm.org/out-of-band/1.1/invitation","@id":"69212a3a-d068-4f9d-a2dd-4741bca89af3","label":"Faber College","goal_code":"issue-vc","goal":"To issue a Faber College Graduate credential","handshake_protocols":["https://didcomm.org/didexchange/1.0","https://didcomm.org/connections/1.0"],"services":["did:sov:LjgpST2rjsoxYegQDRm7EL"]}"#; const OOB_BASE64_URL_ENCODED: &str = "eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0="; - const OOB_URL: &str = "http://example.com/ssi?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0="; + const OOB_URL: &str = "http://example.com/ssi?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0%3D"; // Params mimic example invitation in RFC 0434 - https://github.com/hyperledger/aries-rfcs/tree/main/features/0434-outofband fn _create_invitation() -> Invitation { From 8f225b10b786aef26f047aa6cfcfb8d3bc462b80 Mon Sep 17 00:00:00 2001 From: James Ebert Date: Wed, 21 Aug 2024 18:34:25 -0700 Subject: [PATCH 10/10] chore: adjust base64url encoding to use no padding, remove unnecessary method Signed-off-by: James Ebert --- .../src/handlers/out_of_band/receiver.rs | 57 ++++++------------- .../src/handlers/out_of_band/sender.rs | 9 +-- 2 files changed, 23 insertions(+), 43 deletions(-) diff --git a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs index 7ba18851df..ab1755e3bc 100644 --- a/aries/aries_vcx/src/handlers/out_of_band/receiver.rs +++ b/aries/aries_vcx/src/handlers/out_of_band/receiver.rs @@ -1,6 +1,6 @@ use std::{clone::Clone, fmt::Display, str::FromStr}; -use base64::{engine::general_purpose, prelude::BASE64_URL_SAFE, Engine}; +use base64::{engine::general_purpose, Engine}; use messages::{ decorators::attachment::{Attachment, AttachmentType}, msg_fields::protocols::{ @@ -47,16 +47,6 @@ impl OutOfBandReceiver { }) } - // This is here to help facilitate testing - #[allow(dead_code)] - fn create_from_base64_url_encoded_oob(base64_url_encoded_oob: &str) -> VcxResult { - Ok(Self { - oob: extract_encoded_invitation_from_json_string( - &extract_encoded_invitation_from_base64_url(base64_url_encoded_oob)?, - )?, - }) - } - pub fn create_from_url_encoded_oob(oob_url_string: &str) -> VcxResult { // TODO - URL Shortening Ok(Self { @@ -97,7 +87,7 @@ impl OutOfBandReceiver { } fn invitation_to_base64_url(&self) -> String { - BASE64_URL_SAFE.encode(self.invitation_to_json_string()) + URL_SAFE_LENIENT.encode(self.invitation_to_json_string()) } pub fn invitation_to_url(&self, domain_path: &str) -> VcxResult { @@ -231,10 +221,10 @@ mod tests { "services": ["did:sov:LjgpST2rjsoxYegQDRm7EL"] }"#; const JSON_OOB_INVITE_NO_WHITESPACE: &str = r#"{"@type":"https://didcomm.org/out-of-band/1.1/invitation","@id":"69212a3a-d068-4f9d-a2dd-4741bca89af3","label":"Faber College","goal_code":"issue-vc","goal":"To issue a Faber College Graduate credential","handshake_protocols":["https://didcomm.org/didexchange/1.0","https://didcomm.org/connections/1.0"],"services":["did:sov:LjgpST2rjsoxYegQDRm7EL"]}"#; - const OOB_BASE64_URL_ENCODED: &str = "eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0="; - const OOB_BASE64_URL_ENCODED_NO_PADDING: &str = "eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0"; - const OOB_URL: &str = "http://example.com/ssi?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0%3D"; - const OOB_URL_NOT_PERCENT_ENCODED: &str = "http://example.com/ssi?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0="; + const OOB_BASE64_URL_ENCODED: &str = "eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0"; + const OOB_URL: &str = "http://example.com/ssi?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0"; + const OOB_URL_WITH_PADDING: &str = "http://example.com/ssi?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0%3D"; + const OOB_URL_WITH_PADDING_NOT_PERCENT_ENCODED: &str = "http://example.com/ssi?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0="; // Params mimic example invitation in RFC 0434 - https://github.com/hyperledger/aries-rfcs/tree/main/features/0434-outofband fn _create_invitation() -> Invitation { @@ -287,42 +277,31 @@ mod tests { } #[test] - fn receive_invitation_by_base64_url() { - let base_invite = _create_invitation(); - let parsed_invite = - OutOfBandReceiver::create_from_base64_url_encoded_oob(OOB_BASE64_URL_ENCODED) - .unwrap() - .oob; - assert_eq!(base_invite, parsed_invite); - } - - #[test] - fn receive_invitation_by_base64_url_no_padding() { + fn receive_invitation_by_url() { let base_invite = _create_invitation(); - let parsed_invite = OutOfBandReceiver::create_from_base64_url_encoded_oob( - OOB_BASE64_URL_ENCODED_NO_PADDING, - ) - .unwrap() - .oob; + let parsed_invite = OutOfBandReceiver::create_from_url_encoded_oob(OOB_URL) + .unwrap() + .oob; assert_eq!(base_invite, parsed_invite); } #[test] - fn receive_invitation_by_url() { + fn receive_invitation_by_url_with_padding() { let base_invite = _create_invitation(); - let parsed_invite = OutOfBandReceiver::create_from_url_encoded_oob(OOB_URL) + let parsed_invite = OutOfBandReceiver::create_from_url_encoded_oob(OOB_URL_WITH_PADDING) .unwrap() .oob; assert_eq!(base_invite, parsed_invite); } #[test] - fn receive_invitation_by_url_no_percent_encoding() { + fn receive_invitation_by_url_with_padding_no_percent_encoding() { let base_invite = _create_invitation(); - let parsed_invite = - OutOfBandReceiver::create_from_url_encoded_oob(OOB_URL_NOT_PERCENT_ENCODED) - .unwrap() - .oob; + let parsed_invite = OutOfBandReceiver::create_from_url_encoded_oob( + OOB_URL_WITH_PADDING_NOT_PERCENT_ENCODED, + ) + .unwrap() + .oob; assert_eq!(base_invite, parsed_invite); } diff --git a/aries/aries_vcx/src/handlers/out_of_band/sender.rs b/aries/aries_vcx/src/handlers/out_of_band/sender.rs index 4e9dec96bf..efd5442fdd 100644 --- a/aries/aries_vcx/src/handlers/out_of_band/sender.rs +++ b/aries/aries_vcx/src/handlers/out_of_band/sender.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -use base64::{prelude::BASE64_URL_SAFE, Engine}; +use base64::Engine; use messages::{ msg_fields::protocols::{ cred_issuance::{v1::CredentialIssuanceV1, CredentialIssuance}, @@ -20,6 +20,7 @@ use uuid::Uuid; use crate::{ errors::error::prelude::*, handlers::util::{make_attach_from_str, AttachmentId}, + utils::base64::URL_SAFE_LENIENT, }; #[derive(Debug, PartialEq, Clone)] @@ -139,7 +140,7 @@ impl OutOfBandSender { } fn invitation_to_base64_url(&self) -> String { - BASE64_URL_SAFE.encode(self.invitation_to_json_string()) + URL_SAFE_LENIENT.encode(self.invitation_to_json_string()) } pub fn invitation_to_url(&self, domain_path: &str) -> VcxResult { @@ -177,8 +178,8 @@ mod tests { // Example invite formats referenced (with change to use OOB 1.1) from example invite in RFC 0434 - https://github.com/hyperledger/aries-rfcs/tree/main/features/0434-outofband const JSON_OOB_INVITE_NO_WHITESPACE: &str = r#"{"@type":"https://didcomm.org/out-of-band/1.1/invitation","@id":"69212a3a-d068-4f9d-a2dd-4741bca89af3","label":"Faber College","goal_code":"issue-vc","goal":"To issue a Faber College Graduate credential","handshake_protocols":["https://didcomm.org/didexchange/1.0","https://didcomm.org/connections/1.0"],"services":["did:sov:LjgpST2rjsoxYegQDRm7EL"]}"#; - const OOB_BASE64_URL_ENCODED: &str = "eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0="; - const OOB_URL: &str = "http://example.com/ssi?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0%3D"; + const OOB_BASE64_URL_ENCODED: &str = "eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0"; + const OOB_URL: &str = "http://example.com/ssi?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiI2OTIxMmEzYS1kMDY4LTRmOWQtYTJkZC00NzQxYmNhODlhZjMiLCJsYWJlbCI6IkZhYmVyIENvbGxlZ2UiLCJnb2FsX2NvZGUiOiJpc3N1ZS12YyIsImdvYWwiOiJUbyBpc3N1ZSBhIEZhYmVyIENvbGxlZ2UgR3JhZHVhdGUgY3JlZGVudGlhbCIsImhhbmRzaGFrZV9wcm90b2NvbHMiOlsiaHR0cHM6Ly9kaWRjb21tLm9yZy9kaWRleGNoYW5nZS8xLjAiLCJodHRwczovL2RpZGNvbW0ub3JnL2Nvbm5lY3Rpb25zLzEuMCJdLCJzZXJ2aWNlcyI6WyJkaWQ6c292OkxqZ3BTVDJyanNveFllZ1FEUm03RUwiXX0"; // Params mimic example invitation in RFC 0434 - https://github.com/hyperledger/aries-rfcs/tree/main/features/0434-outofband fn _create_invitation() -> Invitation {