Skip to main content

ssi_data_integrity_core/suite/
mod.rs

1use ssi_claims_core::{
2    ProofPreparationError, ProofValidationError, SignatureEnvironment, SignatureError,
3};
4use ssi_verification_methods::VerificationMethod;
5
6mod signature;
7pub use signature::*;
8
9mod verification;
10pub use verification::*;
11
12use crate::{DataIntegrity, ProofConfiguration, TypeRef};
13
14mod configuration;
15pub use configuration::*;
16
17pub mod bounds;
18pub use bounds::{
19    CloneCryptographicSuite, DebugCryptographicSuite, DeserializeCryptographicSuite,
20    DeserializeCryptographicSuiteOwned, SerializeCryptographicSuite,
21};
22
23use self::standard::{HashingError, TransformationError};
24
25pub mod standard;
26pub use standard::StandardCryptographicSuite;
27
28mod sd;
29pub use sd::*;
30
31/// Cryptographic suite.
32///
33/// See: <https://www.w3.org/TR/vc-data-integrity/#cryptographic-suites>
34pub trait CryptographicSuite: Clone {
35    /// How prepared claims are stored.
36    ///
37    /// This is the output of the hashing algorithm.
38    type PreparedClaims;
39
40    /// Configuration algorithm, used to generate the proof configuration from
41    /// the input options.
42    ///
43    /// Most cryptographic suites will just use the input options as proof
44    /// configuration. Some suites may also use this step to add a custom
45    /// `@context` definition to the proof.
46    type Configuration: ConfigurationAlgorithm<Self>;
47
48    /// Verification method.
49    type VerificationMethod: VerificationMethod;
50
51    /// Suite-specific proof options used to generate the proof.
52    type ProofOptions;
53
54    /// Signature type.
55    ///
56    /// For cryptographic suites conforming to the most recent iteration of
57    /// the Data-Integrity specification, this will be `proofValue`.
58    type Signature: AsRef<str>;
59
60    /// Returns the cryptographic suite type.
61    fn type_(&'_ self) -> TypeRef<'_>;
62
63    /// Generates a proof configuration from input options.
64    fn configure_signature(
65        &self,
66        proof_options: InputProofOptions<Self>,
67        signature_options: InputSignatureOptions<Self>,
68    ) -> Result<(ProofConfiguration<Self>, TransformationOptions<Self>), ConfigurationError> {
69        Self::Configuration::configure_signature(self, proof_options, signature_options)
70    }
71
72    /// Generates a proof configuration from input options.
73    fn configure_verification(
74        &self,
75        verification_options: &InputVerificationOptions<Self>,
76    ) -> Result<TransformationOptions<Self>, ConfigurationError> {
77        Self::Configuration::configure_verification(self, verification_options)
78    }
79
80    /// Generates a verifiable document secured with this cryptographic suite.
81    #[allow(async_fn_in_trait)]
82    async fn sign_with<T, C, R, S>(
83        &self,
84        context: C,
85        unsecured_document: T,
86        resolver: R,
87        signer: S,
88        proof_options: InputProofOptions<Self>,
89        signature_options: InputSignatureOptions<Self>,
90    ) -> Result<DataIntegrity<T, Self>, SignatureError>
91    where
92        Self: CryptographicSuiteSigning<T, C, R, S>,
93    {
94        let (proof_configuration, transformation_options) =
95            self.configure_signature(proof_options, signature_options)?;
96        let proof_configuration_ref = proof_configuration.borrowed();
97        let signature = self
98            .generate_signature(
99                &context,
100                resolver,
101                signer,
102                &unsecured_document,
103                proof_configuration_ref,
104                transformation_options,
105            )
106            .await?;
107
108        let proof = proof_configuration.into_proof(signature);
109        Ok(DataIntegrity::new(unsecured_document, proof.into()))
110    }
111
112    /// Generates a verifiable document secured with this cryptographic suite.
113    #[allow(async_fn_in_trait)]
114    async fn sign<T, R, S>(
115        &self,
116        unsecured_document: T,
117        resolver: R,
118        signer: S,
119        proof_options: InputProofOptions<Self>,
120    ) -> Result<DataIntegrity<T, Self>, SignatureError>
121    where
122        Self: CryptographicSuiteSigning<T, SignatureEnvironment, R, S>,
123        InputSignatureOptions<Self>: Default,
124    {
125        self.sign_with(
126            SignatureEnvironment::default(),
127            unsecured_document,
128            resolver,
129            signer,
130            proof_options,
131            Default::default(),
132        )
133        .await
134    }
135}
136
137#[derive(Debug, thiserror::Error)]
138pub enum ClaimsPreparationError {
139    #[error("proof configuration failed: {0}")]
140    Configuration(#[from] ConfigurationError),
141
142    #[error("claims transformation failed: {0}")]
143    Transformation(#[from] TransformationError),
144
145    #[error("hashing failed: {0}")]
146    Hashing(#[from] HashingError),
147}
148
149impl From<ClaimsPreparationError> for SignatureError {
150    fn from(value: ClaimsPreparationError) -> Self {
151        Self::other(value)
152    }
153}
154
155impl From<ClaimsPreparationError> for ProofValidationError {
156    fn from(value: ClaimsPreparationError) -> Self {
157        Self::Other(value.to_string())
158    }
159}
160
161impl From<ClaimsPreparationError> for ProofPreparationError {
162    fn from(value: ClaimsPreparationError) -> Self {
163        Self::Claims(value.to_string())
164    }
165}