ssi_verification_methods/
methods.rs

1mod w3c;
2use std::borrow::Cow;
3
4use ssi_claims_core::MessageSignatureError;
5use ssi_jwk::JWK;
6use ssi_verification_methods_core::{
7    GenericVerificationMethod, JwkVerificationMethod, MaybeJwkVerificationMethod, SigningMethod,
8};
9pub use w3c::*;
10
11mod unspecified;
12pub use unspecified::*;
13
14ssi_verification_methods_core::complete_verification_method_union! {
15    pub enum AnyMethod, AnyMethodType, AnyMethodTypeRef {
16        /// `Multikey`.
17        Multikey,
18
19        /// `JsonWebKey2020`.
20        JsonWebKey2020,
21
22        /// Deprecated verification method for the `RsaSignature2018` suite.
23        #[cfg(feature = "rsa")]
24        RsaVerificationKey2018,
25
26        /// Deprecated verification method for the `Ed25519Signature2018` suite.
27        #[cfg(feature = "ed25519")]
28        Ed25519VerificationKey2018,
29
30        /// Deprecated verification method for the `Ed25519Signature2020` suite.
31        #[cfg(feature = "ed25519")]
32        Ed25519VerificationKey2020,
33
34        #[cfg(feature = "secp256k1")]
35        EcdsaSecp256k1VerificationKey2019,
36
37        #[cfg(feature = "secp256k1")]
38        EcdsaSecp256k1RecoveryMethod2020,
39
40        #[cfg(feature = "secp256r1")]
41        EcdsaSecp256r1VerificationKey2019,
42
43        #[cfg(all(feature = "tezos", feature = "ed25519"))]
44        Ed25519PublicKeyBLAKE2BDigestSize20Base58CheckEncoded2021,
45
46        #[cfg(all(feature = "tezos", feature = "secp256r1"))]
47        P256PublicKeyBLAKE2BDigestSize20Base58CheckEncoded2021,
48
49        #[cfg(feature = "tezos")]
50        TezosMethod2021,
51
52        #[cfg(feature = "aleo")]
53        AleoMethod2021,
54
55        BlockchainVerificationMethod2021,
56
57        #[cfg(all(feature = "eip712", feature = "secp256k1"))]
58        Eip712Method2021,
59
60        #[cfg(feature = "solana")]
61        SolanaMethod2021
62    }
63}
64
65impl AnyMethod {
66    /// Returns the public key of the verification method as a JWK.
67    ///
68    /// Some methods don't have any the public key embedded.
69    pub fn public_key_jwk(&self) -> Option<Cow<JWK>> {
70        match self {
71            #[cfg(feature = "rsa")]
72            Self::RsaVerificationKey2018(m) => Some(Cow::Borrowed(m.public_key_jwk())),
73            #[cfg(feature = "ed25519")]
74            Self::Ed25519VerificationKey2018(m) => Some(Cow::Owned(m.public_key_jwk())),
75            #[cfg(feature = "ed25519")]
76            Self::Ed25519VerificationKey2020(m) => Some(Cow::Owned(m.public_key_jwk())),
77            #[cfg(feature = "secp256k1")]
78            Self::EcdsaSecp256k1VerificationKey2019(m) => Some(m.public_key_jwk()),
79            #[cfg(feature = "secp256k1")]
80            Self::EcdsaSecp256k1RecoveryMethod2020(m) => m.public_key_jwk(),
81            #[cfg(feature = "secp256r1")]
82            Self::EcdsaSecp256r1VerificationKey2019(m) => Some(Cow::Owned(m.public_key_jwk())),
83            Self::JsonWebKey2020(m) => Some(Cow::Borrowed(m.public_key_jwk())),
84            Self::Multikey(m) => m.public_key_jwk().map(Cow::Owned),
85            #[cfg(all(feature = "tezos", feature = "ed25519"))]
86            Self::Ed25519PublicKeyBLAKE2BDigestSize20Base58CheckEncoded2021(_) => None,
87            #[cfg(all(feature = "tezos", feature = "secp256r1"))]
88            Self::P256PublicKeyBLAKE2BDigestSize20Base58CheckEncoded2021(_) => None,
89            #[cfg(feature = "tezos")]
90            Self::TezosMethod2021(m) => m.public_key_jwk().map(Cow::Borrowed),
91            #[cfg(feature = "aleo")]
92            Self::AleoMethod2021(_) => None,
93            Self::BlockchainVerificationMethod2021(_) => None,
94            #[cfg(all(feature = "eip712", feature = "secp256k1"))]
95            Self::Eip712Method2021(_) => None,
96            #[cfg(feature = "solana")]
97            Self::SolanaMethod2021(m) => Some(Cow::Borrowed(m.public_key_jwk())),
98            _ => None,
99        }
100    }
101}
102
103impl From<AnyMethod> for GenericVerificationMethod {
104    fn from(value: AnyMethod) -> Self {
105        // TODO: implement something better that a JSON roundtrip.
106        let json = serde_json::to_value(value).unwrap();
107        serde_json::from_value(json).unwrap()
108    }
109}
110
111impl MaybeJwkVerificationMethod for AnyMethod {
112    fn try_to_jwk(&self) -> Option<Cow<JWK>> {
113        self.public_key_jwk()
114    }
115}
116
117impl SigningMethod<JWK, ssi_crypto::Algorithm> for AnyMethod {
118    fn sign_bytes(
119        &self,
120        secret: &JWK,
121        algorithm: ssi_crypto::AlgorithmInstance,
122        bytes: &[u8],
123    ) -> Result<Vec<u8>, MessageSignatureError> {
124        match self {
125            #[cfg(feature = "rsa")]
126            Self::RsaVerificationKey2018(m) => m.sign_bytes(bytes, secret),
127            #[cfg(feature = "ed25519")]
128            Self::Ed25519VerificationKey2018(m) => {
129                m.sign_bytes(secret, algorithm.try_into()?, bytes)
130            }
131            #[cfg(feature = "ed25519")]
132            Self::Ed25519VerificationKey2020(m) => match algorithm {
133                ssi_crypto::AlgorithmInstance::EdDSA => m.sign_bytes(secret, bytes),
134                _ => Err(MessageSignatureError::UnsupportedAlgorithm(
135                    algorithm.algorithm().to_string(),
136                )),
137            },
138            #[cfg(feature = "secp256k1")]
139            Self::EcdsaSecp256k1VerificationKey2019(m) => match algorithm {
140                ssi_crypto::AlgorithmInstance::ES256K => m.sign_bytes(
141                    secret,
142                    ecdsa_secp_256k1_verification_key_2019::DigestFunction::Sha256,
143                    bytes,
144                ),
145                _ => Err(MessageSignatureError::UnsupportedAlgorithm(
146                    algorithm.algorithm().to_string(),
147                )),
148            },
149            #[cfg(feature = "secp256k1")]
150            Self::EcdsaSecp256k1RecoveryMethod2020(m) => match algorithm {
151                ssi_crypto::AlgorithmInstance::ES256KR => {
152                    SigningMethod::<_, ssi_crypto::algorithm::ES256KR>::sign_bytes(
153                        m,
154                        secret,
155                        ssi_crypto::algorithm::ES256KR,
156                        bytes,
157                    )
158                }
159                ssi_crypto::AlgorithmInstance::ESKeccakKR => {
160                    SigningMethod::<_, ssi_crypto::algorithm::ESKeccakKR>::sign_bytes(
161                        m,
162                        secret,
163                        ssi_crypto::algorithm::ESKeccakKR,
164                        bytes,
165                    )
166                }
167                _ => Err(MessageSignatureError::UnsupportedAlgorithm(
168                    algorithm.algorithm().to_string(),
169                )),
170            },
171            #[cfg(feature = "secp256r1")]
172            Self::EcdsaSecp256r1VerificationKey2019(m) => match algorithm {
173                ssi_crypto::AlgorithmInstance::ES256 => m.sign_bytes(secret, bytes),
174                _ => Err(MessageSignatureError::UnsupportedAlgorithm(
175                    algorithm.algorithm().to_string(),
176                )),
177            },
178            Self::JsonWebKey2020(m) => m.sign_bytes(secret, Some(algorithm.try_into()?), bytes),
179            Self::Multikey(m) => {
180                SigningMethod::<_, ssi_crypto::Algorithm>::sign_bytes(m, secret, algorithm, bytes)
181            }
182            #[cfg(all(feature = "tezos", feature = "ed25519"))]
183            Self::Ed25519PublicKeyBLAKE2BDigestSize20Base58CheckEncoded2021(m) => {
184                m.sign_bytes(secret, algorithm.try_into()?, bytes)
185            }
186            #[cfg(all(feature = "tezos", feature = "secp256r1"))]
187            Self::P256PublicKeyBLAKE2BDigestSize20Base58CheckEncoded2021(m) => {
188                m.sign_bytes(secret, algorithm.try_into()?, bytes)
189            }
190            #[cfg(feature = "tezos")]
191            Self::TezosMethod2021(m) => m.sign_bytes(secret, algorithm.try_into()?, bytes),
192            #[cfg(feature = "aleo")]
193            Self::AleoMethod2021(m) => {
194                m.sign_bytes(secret, bytes) // FIXME: check key algorithm?
195            }
196            Self::BlockchainVerificationMethod2021(m) => {
197                m.sign_bytes(secret, algorithm.try_into()?, bytes)
198            }
199            #[cfg(all(feature = "eip712", feature = "secp256k1"))]
200            Self::Eip712Method2021(m) => {
201                SigningMethod::sign_bytes(m, secret, algorithm.try_into()?, bytes)
202            }
203            #[cfg(feature = "solana")]
204            Self::SolanaMethod2021(m) => {
205                m.sign_bytes(secret, Some(algorithm.try_into()?), bytes) // FIXME: check algorithm?
206            }
207            m => Err(MessageSignatureError::UnsupportedVerificationMethod(
208                m.type_().name().to_owned(),
209            )),
210        }
211    }
212
213    fn sign_bytes_multi(
214        &self,
215        secret: &JWK,
216        algorithm: ssi_crypto::AlgorithmInstance,
217        messages: &[Vec<u8>],
218    ) -> Result<Vec<u8>, MessageSignatureError> {
219        match self {
220            Self::Multikey(m) => SigningMethod::<_, ssi_crypto::Algorithm>::sign_bytes_multi(
221                m, secret, algorithm, messages,
222            ),
223            m => Err(MessageSignatureError::UnsupportedVerificationMethod(
224                m.type_().name().to_owned(),
225            )),
226        }
227    }
228}
229
230ssi_verification_methods_core::verification_method_union! {
231    pub enum AnyJwkMethod, AnyJwkMethodType {
232        /// `JsonWebKey2020`.
233        JsonWebKey2020,
234
235        /// Deprecated verification method for the `RsaSignature2018` suite.
236        #[cfg(feature = "rsa")]
237        RsaVerificationKey2018,
238
239        /// Deprecated verification method for the `Ed25519Signature2018` suite.
240        #[cfg(feature = "ed25519")]
241        Ed25519VerificationKey2018,
242
243        /// Deprecated verification method for the `Ed25519Signature2020` suite.
244        #[cfg(feature = "ed25519")]
245        Ed25519VerificationKey2020,
246
247        #[cfg(feature = "secp256k1")]
248        EcdsaSecp256k1VerificationKey2019,
249
250        #[cfg(feature = "secp256r1")]
251        EcdsaSecp256r1VerificationKey2019,
252
253        #[cfg(feature = "solana")]
254        SolanaMethod2021
255    }
256}
257
258impl AnyJwkMethod {
259    /// Returns the public key of the verification method as a JWK.
260    ///
261    /// Some methods don't have any the public key embedded.
262    pub fn public_key_jwk(&self) -> Cow<JWK> {
263        match self {
264            Self::JsonWebKey2020(m) => Cow::Borrowed(m.public_key_jwk()),
265            #[cfg(feature = "rsa")]
266            Self::RsaVerificationKey2018(m) => Cow::Borrowed(m.public_key_jwk()),
267            #[cfg(feature = "ed25519")]
268            Self::Ed25519VerificationKey2018(m) => Cow::Owned(m.public_key_jwk()),
269            #[cfg(feature = "ed25519")]
270            Self::Ed25519VerificationKey2020(m) => Cow::Owned(m.public_key_jwk()),
271            #[cfg(feature = "secp256k1")]
272            Self::EcdsaSecp256k1VerificationKey2019(m) => m.public_key_jwk(),
273            #[cfg(feature = "secp256r1")]
274            Self::EcdsaSecp256r1VerificationKey2019(m) => Cow::Owned(m.public_key_jwk()),
275            #[cfg(feature = "solana")]
276            Self::SolanaMethod2021(m) => Cow::Borrowed(m.public_key_jwk()),
277        }
278    }
279}
280
281impl JwkVerificationMethod for AnyJwkMethod {
282    fn to_jwk(&self) -> Cow<JWK> {
283        self.public_key_jwk()
284    }
285}
286
287impl SigningMethod<JWK, ssi_crypto::Algorithm> for AnyJwkMethod {
288    fn sign_bytes(
289        &self,
290        secret: &JWK,
291        algorithm: ssi_crypto::AlgorithmInstance,
292        bytes: &[u8],
293    ) -> Result<Vec<u8>, MessageSignatureError> {
294        match self {
295            #[cfg(feature = "rsa")]
296            Self::RsaVerificationKey2018(m) => m.sign_bytes(bytes, secret),
297            #[cfg(feature = "ed25519")]
298            Self::Ed25519VerificationKey2018(m) => {
299                m.sign_bytes(secret, algorithm.try_into()?, bytes)
300            }
301            #[cfg(feature = "ed25519")]
302            Self::Ed25519VerificationKey2020(m) => match algorithm {
303                ssi_crypto::AlgorithmInstance::EdDSA => m.sign_bytes(secret, bytes),
304                _ => Err(MessageSignatureError::UnsupportedAlgorithm(
305                    algorithm.algorithm().to_string(),
306                )),
307            },
308            #[cfg(feature = "secp256k1")]
309            Self::EcdsaSecp256k1VerificationKey2019(m) => match algorithm {
310                ssi_crypto::AlgorithmInstance::ES256K => m.sign_bytes(
311                    secret,
312                    ecdsa_secp_256k1_verification_key_2019::DigestFunction::Sha256,
313                    bytes,
314                ),
315                _ => Err(MessageSignatureError::UnsupportedAlgorithm(
316                    algorithm.algorithm().to_string(),
317                )),
318            },
319            #[cfg(feature = "secp256r1")]
320            Self::EcdsaSecp256r1VerificationKey2019(m) => match algorithm {
321                ssi_crypto::AlgorithmInstance::ES256 => m.sign_bytes(secret, bytes),
322                _ => Err(MessageSignatureError::UnsupportedAlgorithm(
323                    algorithm.algorithm().to_string(),
324                )),
325            },
326            Self::JsonWebKey2020(m) => m.sign_bytes(secret, Some(algorithm.try_into()?), bytes),
327            #[cfg(feature = "solana")]
328            Self::SolanaMethod2021(m) => {
329                m.sign_bytes(secret, Some(algorithm.try_into()?), bytes) // FIXME: check algorithm?
330            }
331        }
332    }
333}