Skip to content

Commit

Permalink
One step signature and verification (#552)
Browse files Browse the repository at this point in the history
* Remove the `Verifiable` type.

* Simplify signature/verification environment using latest `json-ld`.
  • Loading branch information
timothee-haudebourg authored Jun 25, 2024
1 parent e853fb1 commit b9e988d
Show file tree
Hide file tree
Showing 112 changed files with 1,490 additions and 2,289 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ locspan = "0.8"
json-syntax = "0.12.2"
nquads-syntax = "0.19"
multibase = "0.9.1"
json-ld = "0.16"
serde = "1.0"
serde_json = { version = "1.0", features = ["arbitrary_precision"] }
serde_jcs = "0.1.0"
Expand Down
1 change: 0 additions & 1 deletion crates/claims/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,5 @@ linked-data.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
json-syntax.workspace = true
json-ld.workspace = true
locspan.workspace = true
educe.workspace = true
2 changes: 2 additions & 0 deletions crates/claims/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ ssi-core.workspace = true
educe.workspace = true
thiserror.workspace = true
chrono.workspace = true
ssi-json-ld.workspace = true
ssi-eip712.workspace = true

serde = { workspace = true, optional = true }
linked-data = { workspace = true, optional = true }
186 changes: 1 addition & 185 deletions crates/claims/core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,191 +1,7 @@
use std::ops::Deref;
pub use chrono;

mod signature;
pub use signature::*;

mod verification;
pub use verification::*;

/// Claims serialization utils.
#[cfg(feature = "serde")]
pub mod serde;

/// Claims data-integrity serialization utils.
#[cfg(feature = "linked-data")]
pub mod linked_data;

/// Verifiable claims, and their proof.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Verifiable<Claims, P: Proof> {
/// Claims.
pub claims: Claims,

/// Prepared proof.
///
/// This is not just the proof, but also any information derived from the
/// claims and/or proof required for the verification.
pub proof: P::Prepared,
}

impl<T, P: Proof> Verifiable<T, P> {
pub fn from_parts(claims: T, proof: P::Prepared) -> Self {
Self { claims, proof }
}

pub async fn new<U>(value: U) -> Result<Self, ProofPreparationError>
where
U: ExtractProof<Proofless = T, Proof = P> + DefaultEnvironment,
P: PrepareWith<T, U::Environment>,
{
Self::new_with(value, U::Environment::default()).await
}

pub async fn new_with<U, E>(value: U, mut environment: E) -> Result<Self, ProofPreparationError>
where
U: ExtractProof<Proofless = T, Proof = P>,
P: PrepareWith<T, E>,
{
let (value, raw_proof) = value.extract_proof();
let proof = raw_proof.prepare_with(&value, &mut environment).await?;
Ok(Verifiable::from_parts(value, proof))
}

/// Merge the claims with their proof(s).
///
/// This will effectively unprepare the proof and make them unverifiable
/// until [`Self::new`] is called again.
pub fn unprepare(self) -> P::Attached
where
P: AttachProof<T>,
P::Prepared: UnprepareProof<Unprepared = P>,
{
let (claims, prepared_proof) = self.into_parts();
prepared_proof.unprepare().attach_to(claims)
}

/// Tamper with the claims without changing the proofs.
///
/// The proofs may become invalid.
pub async fn tamper<U, E>(
self,
environment: E,
f: impl FnOnce(T) -> U,
) -> Result<Verifiable<U, P>, ProofPreparationError>
where
P: PrepareWith<U, E>,
P::Prepared: UnprepareProof<Unprepared = P>,
{
self.tamper_with_proofs(environment, f, |p| p).await
}

/// Tamper with the claims and proofs.
///
/// The proofs may become invalid.
pub async fn tamper_with_proofs<U, E>(
self,
mut environment: E,
f: impl FnOnce(T) -> U,
mut g: impl FnMut(P) -> P,
) -> Result<Verifiable<U, P>, ProofPreparationError>
where
P: PrepareWith<U, E>,
P::Prepared: UnprepareProof<Unprepared = P>,
{
self.async_try_map(|value, proof| async {
let u = f(value);

let unprepared_proof = g(proof.unprepare());
let new_proof = unprepared_proof.prepare_with(&u, &mut environment).await?;

Ok((u, new_proof))
})
.await
}

/// Validates the claims and verify them against the proof.
pub async fn verify<V>(&self, verifier: &V) -> Result<Verification, ProofValidationError>
where
T: Validate<ValidationEnvironment, P>,
P::Prepared: ValidateProof<T, V>,
{
let env = ValidationEnvironment::default();
self.verify_with(verifier, &env).await
}

/// Validates the claims and verify them against the proof.
pub async fn verify_with<V, E>(
&self,
verifier: &V,
env: &E,
) -> Result<Verification, ProofValidationError>
where
T: Validate<E, P>,
P::Prepared: ValidateProof<T, V>,
{
match self.claims.validate(env, &self.proof) {
Ok(_) => self
.proof
.validate_proof(&self.claims, verifier)
.await
.map(|r| r.map_err(Invalid::Proof)),
Err(e) => {
// Claims are not valid on their own.
Ok(Err(Invalid::Claims(e)))
}
}
}

pub fn map<D, Q: Proof>(
self,
f: impl FnOnce(T, P::Prepared) -> (D, Q::Prepared),
) -> Verifiable<D, Q> {
let (claims, proof) = f(self.claims, self.proof);

Verifiable { claims, proof }
}

pub fn try_map<D, Q: Proof, E>(
self,
f: impl FnOnce(T, P::Prepared) -> Result<(D, Q::Prepared), E>,
) -> Result<Verifiable<D, Q>, E> {
let (claims, proof) = f(self.claims, self.proof)?;

Ok(Verifiable { claims, proof })
}

pub async fn async_map<D, Q: Proof, F>(
self,
f: impl FnOnce(T, P::Prepared) -> F,
) -> Verifiable<D, Q>
where
F: std::future::Future<Output = (D, Q::Prepared)>,
{
let (claims, proof) = f(self.claims, self.proof).await;

Verifiable { claims, proof }
}

pub async fn async_try_map<D, Q: Proof, E, F>(
self,
f: impl FnOnce(T, P::Prepared) -> F,
) -> Result<Verifiable<D, Q>, E>
where
F: std::future::Future<Output = Result<(D, Q::Prepared), E>>,
{
let (claims, proof) = f(self.claims, self.proof).await?;

Ok(Verifiable { claims, proof })
}

pub fn into_parts(self) -> (T, P::Prepared) {
(self.claims, self.proof)
}
}

impl<C, P: Proof> Deref for Verifiable<C, P> {
type Target = C;

fn deref(&self) -> &Self::Target {
&self.claims
}
}
76 changes: 0 additions & 76 deletions crates/claims/core/src/linked_data.rs

This file was deleted.

41 changes: 0 additions & 41 deletions crates/claims/core/src/serde.rs

This file was deleted.

Loading

0 comments on commit b9e988d

Please sign in to comment.