diff --git a/src/ecdsa_xi_2023.rs b/src/ecdsa_xi_2023.rs index 88f5e52..a62603c 100644 --- a/src/ecdsa_xi_2023.rs +++ b/src/ecdsa_xi_2023.rs @@ -22,28 +22,25 @@ use ssi::{ rdf::{AnyLdEnvironment, LdEnvironment}, verification_methods::{multikey, Multikey}, }; -use std::marker::PhantomData; /// The `ecdsa-xi-2023` cryptosuite. /// /// See: #[derive(Debug, Default, Clone, Copy)] -pub struct EcdsaXi2023(PhantomData); +pub struct EcdsaXi2023; -impl TryFrom for EcdsaXi2023 { +impl TryFrom for EcdsaXi2023 { type Error = UnsupportedProofSuite; fn try_from(value: Type) -> Result { match value { - Type::DataIntegrityProof(cryptosuite) if cryptosuite == "ecdsa-xi-2023" => { - Ok(Self(PhantomData)) - } + Type::DataIntegrityProof(cryptosuite) if cryptosuite == "ecdsa-xi-2023" => Ok(Self), other => Err(UnsupportedProofSuite::Compact(other)), } } } -impl<'a> StandardCryptographicSuite for EcdsaXi2023<&'a [u8]> { +impl StandardCryptographicSuite for EcdsaXi2023 { type Configuration = EcdsaXi2023ConfigurationAlgorithm; type Transformation = EcdsaXi2023TransformationAlgorithm; @@ -61,54 +58,47 @@ impl<'a> StandardCryptographicSuite for EcdsaXi2023<&'a [u8]> { } } -#[derive(Debug, Clone, Copy)] -pub struct ExtraInformation<'a>(pub &'a [u8]); +#[derive(Debug, Clone)] +pub struct ExtraInformation(pub Vec); pub struct EcdsaXi2023ConfigurationAlgorithm; -impl<'a> ConfigurationAlgorithm> for EcdsaXi2023ConfigurationAlgorithm { +impl ConfigurationAlgorithm for EcdsaXi2023ConfigurationAlgorithm { type InputVerificationMethod = Multikey; type InputSuiteOptions = (); - type InputSignatureOptions = ExtraInformation<'a>; - type InputVerificationOptions = ExtraInformation<'a>; - type TransformationOptions = ExtraInformation<'a>; + type InputSignatureOptions = ExtraInformation; + type InputVerificationOptions = ExtraInformation; + type TransformationOptions = ExtraInformation; fn configure_signature( - suite: &EcdsaXi2023<&'a [u8]>, + suite: &EcdsaXi2023, proof_options: ProofOptions, - signature_options: ExtraInformation<'a>, - ) -> Result< - ( - ProofConfiguration>, - ExtraInformation<'a>, - ), - ConfigurationError, - > { + signature_options: ExtraInformation, + ) -> Result<(ProofConfiguration, ExtraInformation), ConfigurationError> { let configuration = proof_options.into_configuration(*suite)?; Ok((configuration, signature_options)) } fn configure_verification( - _suite: &EcdsaXi2023<&'a [u8]>, - verification_options: &ExtraInformation<'a>, - ) -> Result, ConfigurationError> { - Ok(*verification_options) + _suite: &EcdsaXi2023, + verification_options: &ExtraInformation, + ) -> Result { + Ok(verification_options.clone()) } } -pub struct WithExtraInformation<'a, T> { +pub struct WithExtraInformation { data: T, - extra_information: &'a [u8], + extra_information: Vec, } pub struct EcdsaXi2023TransformationAlgorithm; -impl<'a> TransformationAlgorithm> for EcdsaXi2023TransformationAlgorithm { - type Output = WithExtraInformation<'a, CanonicalClaimsAndConfiguration>; +impl TransformationAlgorithm for EcdsaXi2023TransformationAlgorithm { + type Output = WithExtraInformation; } -impl<'a, T, C> TypedTransformationAlgorithm, T, C> - for EcdsaXi2023TransformationAlgorithm +impl TypedTransformationAlgorithm for EcdsaXi2023TransformationAlgorithm where T: JsonLdNodeObject + Expandable, C: JsonLdLoaderProvider, @@ -116,9 +106,9 @@ where async fn transform( context: &C, data: &T, - proof_configuration: ProofConfigurationRef<'_, EcdsaXi2023<&'a [u8]>>, + proof_configuration: ProofConfigurationRef<'_, EcdsaXi2023>, _verification_method: &Multikey, - transformation_options: ExtraInformation<'a>, + transformation_options: ExtraInformation, ) -> Result { let mut ld = LdEnvironment::default(); @@ -145,12 +135,12 @@ where pub struct EcdsaXi2023HashingAlgorithm; -impl<'a> HashingAlgorithm> for EcdsaXi2023HashingAlgorithm { +impl HashingAlgorithm for EcdsaXi2023HashingAlgorithm { type Output = EcdsaXi2023Hash; fn hash( input: WithExtraInformation, - _proof_configuration: ProofConfigurationRef>, + _proof_configuration: ProofConfigurationRef, verification_method: &Multikey, ) -> Result { match verification_method diff --git a/src/optical_barcode_credential/compression/encoding.rs b/src/optical_barcode_credential/compression/encoding.rs index d01b2cb..78fa1c6 100644 --- a/src/optical_barcode_credential/compression/encoding.rs +++ b/src/optical_barcode_credential/compression/encoding.rs @@ -14,8 +14,8 @@ fn encode_options() -> EncodeOptions { } } -pub async fn encode<'a, T>( - vc: &DataIntegrity, EcdsaXi2023<&'a [u8]>>, +pub async fn encode( + vc: &DataIntegrity, EcdsaXi2023>, ) -> cbor_ld::CborValue where T: OpticalBarcodeCredentialSubject, @@ -26,8 +26,8 @@ where .unwrap() } -pub async fn encode_to_bytes<'a, T>( - vc: &DataIntegrity, EcdsaXi2023<&'a [u8]>>, +pub async fn encode_to_bytes( + vc: &DataIntegrity, EcdsaXi2023>, ) -> Vec where T: OpticalBarcodeCredentialSubject, diff --git a/src/optical_barcode_credential/mod.rs b/src/optical_barcode_credential/mod.rs index 8286996..e35c0d8 100644 --- a/src/optical_barcode_credential/mod.rs +++ b/src/optical_barcode_credential/mod.rs @@ -53,29 +53,3 @@ pub unsafe trait OpticalBarcodeCredentialSubject: Serialize + DeserializeOwned { fn create_optical_data(&self, xi: &Self::ExtraInformation) -> [u8; 32]; } - -pub fn change_xi_lifetime<'a, 'b, T: OpticalBarcodeCredentialSubject>( - vc: DataIntegrity, EcdsaXi2023<&'a [u8]>>, -) -> DataIntegrity, EcdsaXi2023<&'b [u8]>> { - unsafe { - // SAFETY: the lifetime in `EcdsaXi2023` is completely unused, - // it does not refer any data stored in `vc`. - std::mem::transmute::< - DataIntegrity, EcdsaXi2023<&'a [u8]>>, - DataIntegrity, EcdsaXi2023<&'b [u8]>>, - >(vc) - } -} - -pub fn change_xi_lifetime_ref<'r, 'a, 'b, T: OpticalBarcodeCredentialSubject>( - vc: &'r DataIntegrity, EcdsaXi2023<&'a [u8]>>, -) -> &'r DataIntegrity, EcdsaXi2023<&'b [u8]>> { - unsafe { - // SAFETY: the lifetime in `EcdsaXi2023` is completely unused, - // it does not refer any data stored in `vc`. - std::mem::transmute::< - &'r DataIntegrity, EcdsaXi2023<&'a [u8]>>, - &'r DataIntegrity, EcdsaXi2023<&'b [u8]>>, - >(vc) - } -} diff --git a/src/optical_barcode_credential/signature.rs b/src/optical_barcode_credential/signature.rs index e0a596f..e804783 100644 --- a/src/optical_barcode_credential/signature.rs +++ b/src/optical_barcode_credential/signature.rs @@ -15,9 +15,7 @@ use crate::{ terse_bitstring_status_list_entry::TerseBitstringStatusListEntry, }; -use super::{ - change_xi_lifetime, OpticalBarcodeCredential, OpticalBarcodeCredentialSubject, CONTEXT_LOADER, -}; +use super::{OpticalBarcodeCredential, OpticalBarcodeCredentialSubject, CONTEXT_LOADER}; /// Optical barcode credential signature parameters. pub struct SignatureParameters { @@ -100,7 +98,7 @@ where pub async fn sign_from_optical_data( mut unsigned: OpticalBarcodeCredential, - optical_data: &[u8], + optical_data: impl Into>, options: ProofOptions, params: SignatureParameters, ) -> Result, EcdsaXi2023>, SignatureError> @@ -120,18 +118,16 @@ where ) } - let vc = EcdsaXi2023::<&[u8]>::default() + EcdsaXi2023 .sign_with( XiSignatureEnvironment(&*CONTEXT_LOADER), unsigned, params.resolver, params.signer, options, - ExtraInformation(optical_data), + ExtraInformation(optical_data.into()), ) - .await?; - - Ok(change_xi_lifetime(vc)) + .await } struct XiSignatureEnvironment<'a, L>(&'a L); @@ -148,3 +144,48 @@ pub struct Status { entry: BitstringStatusListEntry, list_len: usize, } + +#[cfg(test)] +mod tests { + use ssi::{ + claims::data_integrity::ProofOptions, + dids::{AnyDidMethod, DIDKey, DIDResolver}, + verification_methods::SingleSecretSigner, + JWK, + }; + use static_iref::uri; + + use crate::{create, MachineReadableZone, MRZ}; + + use super::SignatureParameters; + + fn assert_send(_: impl Send) {} + + const MRZ_DATA: MRZ = [ + *b"IAUTO0000007010SRC0000000701<<", + *b"8804192M2601058NOT<<<<<<<<<<<5", + *b"SMITH< { @@ -45,8 +42,8 @@ impl VerificationParameters { } } -pub async fn verify<'a, T, R, C>( - vc: &DataIntegrity, EcdsaXi2023<&'a [u8]>>, +pub async fn verify( + vc: &DataIntegrity, EcdsaXi2023>, extra_information: &T::ExtraInformation, params: VerificationParameters, ) -> Result @@ -63,9 +60,9 @@ where verify_from_optical_data(vc, &optical_data, params).await } -pub async fn verify_from_optical_data<'a, 'b, T, R, C>( - vc: &DataIntegrity, EcdsaXi2023<&'b [u8]>>, - optical_data: &'a [u8], +pub async fn verify_from_optical_data( + vc: &DataIntegrity, EcdsaXi2023>, + optical_data: impl Into>, params: VerificationParameters, ) -> Result where @@ -73,9 +70,6 @@ where R: VerificationMethodResolver, C: TerseStatusListProvider, { - let vc: &DataIntegrity, EcdsaXi2023<&'a [u8]>> = - change_xi_lifetime_ref(vc); - for terse_entry in &vc.credential_status { let client = params .status_list_client @@ -108,7 +102,7 @@ where } let params = XiVerificationParameters::new( - optical_data, + optical_data.into(), ssi::claims::VerificationParameters { resolver: params.resolver, json_ld_loader: &*CONTEXT_LOADER, @@ -120,13 +114,13 @@ where vc.verify(params).await } -struct XiVerificationParameters<'a, P> { - extra_information: ExtraInformation<'a>, +struct XiVerificationParameters

{ + extra_information: ExtraInformation, params: P, } -impl<'a, P> XiVerificationParameters<'a, P> { - fn new(extra_information: &'a [u8], params: P) -> Self { +impl

XiVerificationParameters

{ + fn new(extra_information: Vec, params: P) -> Self { Self { extra_information: ExtraInformation(extra_information), params, @@ -134,7 +128,7 @@ impl<'a, P> XiVerificationParameters<'a, P> { } } -impl<'a, P: DateTimeProvider> DateTimeProvider for XiVerificationParameters<'a, P> { +impl DateTimeProvider for XiVerificationParameters

{ fn date_time( &self, ) -> ssi::claims::chrono::prelude::DateTime { @@ -142,7 +136,7 @@ impl<'a, P: DateTimeProvider> DateTimeProvider for XiVerificationParameters<'a, } } -impl<'a, P: ResolverProvider> ResolverProvider for XiVerificationParameters<'a, P> { +impl ResolverProvider for XiVerificationParameters

{ type Resolver = P::Resolver; fn resolver(&self) -> &Self::Resolver { @@ -150,7 +144,7 @@ impl<'a, P: ResolverProvider> ResolverProvider for XiVerificationParameters<'a, } } -impl<'a, P: JsonLdLoaderProvider> JsonLdLoaderProvider for XiVerificationParameters<'a, P> { +impl JsonLdLoaderProvider for XiVerificationParameters

{ type Loader = P::Loader; fn loader(&self) -> &Self::Loader { @@ -158,8 +152,35 @@ impl<'a, P: JsonLdLoaderProvider> JsonLdLoaderProvider for XiVerificationParamet } } -impl<'a, P> ResourceProvider> for XiVerificationParameters<'a, P> { - fn get_resource(&self) -> &ExtraInformation<'a> { +impl

ResourceProvider for XiVerificationParameters

{ + fn get_resource(&self) -> &ExtraInformation { &self.extra_information } } + +#[cfg(test)] +mod tests { + use ssi::dids::{AnyDidMethod, DIDResolver}; + + use crate::{optical_barcode_credential::decode_from_bytes, verify, MachineReadableZone, MRZ}; + + fn assert_send(_: impl Send) {} + + const MRZ_DATA: MRZ = [ + *b"IAUTO0000007010SRC0000000701<<", + *b"8804192M2601058NOT<<<<<<<<<<<5", + *b"SMITH<(&input) + .await + .unwrap(); + let params = super::VerificationParameters::new(AnyDidMethod::default().into_vm_resolver()); + assert_send(verify(&vc, &MRZ_DATA, params)) + } +}