ssi_data_integrity_core/signing/
multibase.rs1use std::marker::PhantomData;
2
3use multibase::Base;
4use ssi_claims_core::{ProofValidationError, ProofValidity, SignatureError};
5use ssi_crypto::algorithm::SignatureAlgorithmInstance;
6use ssi_verification_methods::{MessageSigner, VerifyBytes};
7
8use crate::{
9 suite::standard::{
10 SignatureAlgorithm, SignatureAndVerificationAlgorithm, VerificationAlgorithm,
11 },
12 CryptographicSuite, ProofConfigurationRef, ProofRef,
13};
14
15use super::AlgorithmSelection;
16
17#[derive(
19 Debug,
20 Clone,
21 serde::Serialize,
22 serde::Deserialize,
23 linked_data::Serialize,
24 linked_data::Deserialize,
25)]
26#[ld(prefix("sec" = "https://w3id.org/security#"))]
27pub struct MultibaseSignature {
28 #[serde(rename = "proofValue")]
30 #[ld("sec:proofValue")]
31 pub proof_value: String,
32}
33
34impl MultibaseSignature {
35 pub fn new(signature: Vec<u8>, base: Base) -> Self {
36 Self {
37 proof_value: multibase::encode(base, signature),
38 }
39 }
40
41 pub fn new_base58btc(signature: Vec<u8>) -> Self {
42 Self {
43 proof_value: multibase::encode(Base::Base58Btc, signature),
44 }
45 }
46
47 pub fn decode(&self) -> Result<(Base, Vec<u8>), ProofValidationError> {
48 multibase::decode(&self.proof_value).map_err(|_| ProofValidationError::InvalidSignature)
49 }
50}
51
52impl AsRef<str> for MultibaseSignature {
53 fn as_ref(&self) -> &str {
54 &self.proof_value
55 }
56}
57
58impl super::AlterSignature for MultibaseSignature {
59 fn alter(&mut self) {
60 self.proof_value.push_str("ff")
61 }
62}
63
64pub trait StaticBase {
65 const BASE: Base;
66}
67
68pub struct Base58Btc;
69
70impl StaticBase for Base58Btc {
71 const BASE: Base = Base::Base58Btc;
72}
73
74pub struct MultibaseSigning<A, B>(PhantomData<(A, B)>);
75
76impl<A, B> SignatureAndVerificationAlgorithm for MultibaseSigning<A, B> {
77 type Signature = MultibaseSignature;
78}
79
80impl<A, B, S, T> SignatureAlgorithm<S, T> for MultibaseSigning<A, B>
81where
82 S: CryptographicSuite,
83 S::PreparedClaims: AsRef<[u8]>,
84 A: AlgorithmSelection<S::VerificationMethod, S::ProofOptions>,
85 B: StaticBase,
86 T: MessageSigner<A>,
87{
88 async fn sign(
89 verification_method: &S::VerificationMethod,
90 signer: T,
91 prepared_claims: S::PreparedClaims,
92 proof_configuration: ProofConfigurationRef<'_, S>,
93 ) -> Result<Self::Signature, SignatureError> {
94 let algorithm = A::select_algorithm(verification_method, proof_configuration.options)?;
95
96 Ok(MultibaseSignature::new(
97 signer.sign(algorithm, prepared_claims.as_ref()).await?,
98 B::BASE,
99 ))
100 }
101}
102
103impl<A, B, S> VerificationAlgorithm<S> for MultibaseSigning<A, B>
104where
105 S: CryptographicSuite<Signature = MultibaseSignature>,
106 S::PreparedClaims: AsRef<[u8]>,
107 S::VerificationMethod: VerifyBytes<A>,
108 A: AlgorithmSelection<S::VerificationMethod, S::ProofOptions>,
109 B: StaticBase,
110{
111 fn verify(
112 verification_method: &S::VerificationMethod,
113 prepared_claims: S::PreparedClaims,
114 proof: ProofRef<S>,
115 ) -> Result<ProofValidity, ProofValidationError> {
116 let algorithm_instance = A::select_algorithm(verification_method, proof.options)?;
117
118 let (_, signature_bytes) = proof.signature.decode()?; verification_method.verify_bytes(
120 algorithm_instance.algorithm(),
121 prepared_claims.as_ref(),
122 &signature_bytes,
123 )
124 }
125}