Skip to content

Commit

Permalink
fix: #1053 Base64URLSafe padded and unpadded decoding (#1083)
Browse files Browse the repository at this point in the history
* lli - Allow decoding both padded and unpadded Base64 data

Signed-off-by: lli <lli@anonyome.com>

* lli - Running cargo fmt

Signed-off-by: lli <lli@anonyome.com>

* lli - improve testing rigor

Signed-off-by: lli <lli@anonyome.com>

* lli - custom GeneralPurpose engine instance for indifferent decode

Signed-off-by: lli <lli@anonyome.com>

* lli - move custom engine to utils

Signed-off-by: lli <lli@anonyome.com>

---------

Signed-off-by: lli <lli@anonyome.com>
  • Loading branch information
lukewli-anonyome authored Dec 19, 2023
1 parent bfd2c1f commit db8c27a
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 9 deletions.
45 changes: 36 additions & 9 deletions aries/aries_vcx/src/common/signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,17 @@ use messages::msg_fields::protocols::connection::{
};
use time;

use crate::errors::error::prelude::*;
use crate::{errors::error::prelude::*, utils::base64::URL_SAFE_LENIENT};

// Utility function to handle both padded and unpadded Base64URL data
fn base64url_decode(encoded: &str) -> VcxResult<Vec<u8>> {
URL_SAFE_LENIENT.decode(encoded).map_err(|err| {
AriesVcxError::from_msg(
AriesVcxErrorKind::InvalidJson,
format!("Cannot decode Base64URL data: {:?}", err),
)
})
}

async fn get_signature_data(
wallet: &impl BaseWallet,
Expand Down Expand Up @@ -52,14 +62,7 @@ pub async fn decode_signed_connection_response(
)
})?;

let sig_data = general_purpose::URL_SAFE
.decode(response.connection_sig.sig_data.as_bytes())
.map_err(|err| {
AriesVcxError::from_msg(
AriesVcxErrorKind::InvalidJson,
format!("Cannot decode ConnectionResponse: {:?}", err),
)
})?;
let sig_data = base64url_decode(&response.connection_sig.sig_data)?;

if !wallet.verify(their_vk, &sig_data, &signature).await? {
return Err(AriesVcxError::from_msg(
Expand Down Expand Up @@ -146,3 +149,27 @@ pub async fn decode_signed_connection_response(
// .await;
// }
// }

#[cfg(test)]
mod tests {
use super::*;

#[tokio::test]
async fn test_decode_padded_and_unpadded_sig_data() {
let encoded_padded = "T3BlbkFJIENoYXRHUFQ=";
let encoded_unpadded = "T3BlbkFJIENoYXRHUFQ";

let decoded_padded = base64url_decode(encoded_padded).unwrap();
let decoded_unpadded = base64url_decode(encoded_unpadded).unwrap();

assert_eq!(decoded_padded, decoded_unpadded);
}

#[tokio::test]
async fn test_invalid_json_error() {
let non_json_input = "Not a JSON input";
let result = base64url_decode(non_json_input);
let error = result.unwrap_err();
assert!(matches!(error.kind(), AriesVcxErrorKind::InvalidJson));
}
}
13 changes: 13 additions & 0 deletions aries/aries_vcx/src/utils/base64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use base64::{
alphabet,
engine::{DecodePaddingMode, GeneralPurpose, GeneralPurposeConfig},
};

/// A default [GeneralPurposeConfig] configuration with a [decode_padding_mode] of
/// [DecodePaddingMode::Indifferent]
pub const LENIENT_PAD: GeneralPurposeConfig =
GeneralPurposeConfig::new().with_decode_padding_mode(DecodePaddingMode::Indifferent);

/// A [GeneralPurpose] engine using the [alphabet::URL_SAFE] base64 alphabet and
/// [DecodePaddingMode::Indifferent] config to decode both padded and unpadded.
pub const URL_SAFE_LENIENT: GeneralPurpose = GeneralPurpose::new(&alphabet::URL_SAFE, LENIENT_PAD);
1 change: 1 addition & 0 deletions aries/aries_vcx/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ macro_rules! secret {
}};
}

pub mod base64;
pub mod openssl;
pub mod qualifier;

Expand Down

0 comments on commit db8c27a

Please sign in to comment.