Skip to content

Commit

Permalink
Remove the lifetime in EcdsaXi2023. (#2)
Browse files Browse the repository at this point in the history
The extra data is now passed by copy.
Fixes #1
  • Loading branch information
timothee-haudebourg authored Aug 7, 2024
1 parent 93b9bdb commit 4d078d5
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 97 deletions.
62 changes: 26 additions & 36 deletions src/ecdsa_xi_2023.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,25 @@ use ssi::{
rdf::{AnyLdEnvironment, LdEnvironment},
verification_methods::{multikey, Multikey},
};
use std::marker::PhantomData;

/// The `ecdsa-xi-2023` cryptosuite.
///
/// See: <https://w3c-ccg.github.io/vc-barcodes/#ecdsa-xi-2023>
#[derive(Debug, Default, Clone, Copy)]
pub struct EcdsaXi2023<X = &'static [u8]>(PhantomData<X>);
pub struct EcdsaXi2023;

impl<X> TryFrom<Type> for EcdsaXi2023<X> {
impl TryFrom<Type> for EcdsaXi2023 {
type Error = UnsupportedProofSuite;

fn try_from(value: Type) -> Result<Self, Self::Error> {
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;
Expand All @@ -61,64 +58,57 @@ 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<u8>);

pub struct EcdsaXi2023ConfigurationAlgorithm;

impl<'a> ConfigurationAlgorithm<EcdsaXi2023<&'a [u8]>> for EcdsaXi2023ConfigurationAlgorithm {
impl ConfigurationAlgorithm<EcdsaXi2023> 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<Multikey, ()>,
signature_options: ExtraInformation<'a>,
) -> Result<
(
ProofConfiguration<EcdsaXi2023<&'a [u8]>>,
ExtraInformation<'a>,
),
ConfigurationError,
> {
signature_options: ExtraInformation,
) -> Result<(ProofConfiguration<EcdsaXi2023>, 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<ExtraInformation<'a>, ConfigurationError> {
Ok(*verification_options)
_suite: &EcdsaXi2023,
verification_options: &ExtraInformation,
) -> Result<ExtraInformation, ConfigurationError> {
Ok(verification_options.clone())
}
}

pub struct WithExtraInformation<'a, T> {
pub struct WithExtraInformation<T> {
data: T,
extra_information: &'a [u8],
extra_information: Vec<u8>,
}

pub struct EcdsaXi2023TransformationAlgorithm;

impl<'a> TransformationAlgorithm<EcdsaXi2023<&'a [u8]>> for EcdsaXi2023TransformationAlgorithm {
type Output = WithExtraInformation<'a, CanonicalClaimsAndConfiguration>;
impl TransformationAlgorithm<EcdsaXi2023> for EcdsaXi2023TransformationAlgorithm {
type Output = WithExtraInformation<CanonicalClaimsAndConfiguration>;
}

impl<'a, T, C> TypedTransformationAlgorithm<EcdsaXi2023<&'a [u8]>, T, C>
for EcdsaXi2023TransformationAlgorithm
impl<T, C> TypedTransformationAlgorithm<EcdsaXi2023, T, C> for EcdsaXi2023TransformationAlgorithm
where
T: JsonLdNodeObject + Expandable,
C: JsonLdLoaderProvider,
{
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<Self::Output, TransformationError> {
let mut ld = LdEnvironment::default();

Expand All @@ -145,12 +135,12 @@ where

pub struct EcdsaXi2023HashingAlgorithm;

impl<'a> HashingAlgorithm<EcdsaXi2023<&'a [u8]>> for EcdsaXi2023HashingAlgorithm {
impl HashingAlgorithm<EcdsaXi2023> for EcdsaXi2023HashingAlgorithm {
type Output = EcdsaXi2023Hash;

fn hash(
input: WithExtraInformation<CanonicalClaimsAndConfiguration>,
_proof_configuration: ProofConfigurationRef<EcdsaXi2023<&'a [u8]>>,
_proof_configuration: ProofConfigurationRef<EcdsaXi2023>,
verification_method: &Multikey,
) -> Result<Self::Output, HashingError> {
match verification_method
Expand Down
8 changes: 4 additions & 4 deletions src/optical_barcode_credential/compression/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ fn encode_options() -> EncodeOptions {
}
}

pub async fn encode<'a, T>(
vc: &DataIntegrity<OpticalBarcodeCredential<T>, EcdsaXi2023<&'a [u8]>>,
pub async fn encode<T>(
vc: &DataIntegrity<OpticalBarcodeCredential<T>, EcdsaXi2023>,
) -> cbor_ld::CborValue
where
T: OpticalBarcodeCredentialSubject,
Expand All @@ -26,8 +26,8 @@ where
.unwrap()
}

pub async fn encode_to_bytes<'a, T>(
vc: &DataIntegrity<OpticalBarcodeCredential<T>, EcdsaXi2023<&'a [u8]>>,
pub async fn encode_to_bytes<T>(
vc: &DataIntegrity<OpticalBarcodeCredential<T>, EcdsaXi2023>,
) -> Vec<u8>
where
T: OpticalBarcodeCredentialSubject,
Expand Down
26 changes: 0 additions & 26 deletions src/optical_barcode_credential/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<OpticalBarcodeCredential<T>, EcdsaXi2023<&'a [u8]>>,
) -> DataIntegrity<OpticalBarcodeCredential<T>, 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<OpticalBarcodeCredential<T>, EcdsaXi2023<&'a [u8]>>,
DataIntegrity<OpticalBarcodeCredential<T>, EcdsaXi2023<&'b [u8]>>,
>(vc)
}
}

pub fn change_xi_lifetime_ref<'r, 'a, 'b, T: OpticalBarcodeCredentialSubject>(
vc: &'r DataIntegrity<OpticalBarcodeCredential<T>, EcdsaXi2023<&'a [u8]>>,
) -> &'r DataIntegrity<OpticalBarcodeCredential<T>, 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<OpticalBarcodeCredential<T>, EcdsaXi2023<&'a [u8]>>,
&'r DataIntegrity<OpticalBarcodeCredential<T>, EcdsaXi2023<&'b [u8]>>,
>(vc)
}
}
59 changes: 50 additions & 9 deletions src/optical_barcode_credential/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<R, S> {
Expand Down Expand Up @@ -100,7 +98,7 @@ where

pub async fn sign_from_optical_data<T, R, S>(
mut unsigned: OpticalBarcodeCredential<T>,
optical_data: &[u8],
optical_data: impl Into<Vec<u8>>,
options: ProofOptions<ssi::verification_methods::Multikey, ()>,
params: SignatureParameters<R, S>,
) -> Result<DataIntegrity<OpticalBarcodeCredential<T>, EcdsaXi2023>, SignatureError>
Expand All @@ -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);
Expand All @@ -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<<JOHN<<<<<<<<<<<<<<<<<<<",
];

#[async_std::test]
async fn create_is_send() {
let jwk = JWK::generate_p256();

let vm = DIDKey::generate_url(&jwk).unwrap();
let options = ProofOptions::from_method(vm.into_iri().into());

let params = SignatureParameters::new(
AnyDidMethod::default().into_vm_resolver(),
SingleSecretSigner::new(jwk),
None,
);

assert_send(create(
&MRZ_DATA,
uri!("http://example.org/issuer").to_owned(),
MachineReadableZone {},
options,
params,
))
}
}
Loading

0 comments on commit 4d078d5

Please sign in to comment.