Skip to main content

crypto_dispatch/registry/
signature.rs

1// SPDX-FileCopyrightText: Copyright © 2026 ReallyMe LLC. All rights reserved
2//
3// SPDX-License-Identifier: Apache-2.0
4
5use crate::provider::ProviderOperation;
6#[cfg(any(
7    feature = "ed25519",
8    feature = "p256",
9    feature = "p384",
10    feature = "p521",
11    feature = "secp256k1",
12    feature = "ml-dsa-44",
13    feature = "ml-dsa-65",
14    feature = "ml-dsa-87"
15))]
16use crate::traits::SignatureAlgorithm;
17use crate::AlgorithmError;
18use crypto_core::Algorithm;
19
20/// Sign `msg` with `secret` under the selected signature algorithm,
21/// returning the detached signature bytes.
22///
23/// The crate README contains the compile-checked signature example so test
24/// code remains separate from this production implementation.
25pub fn sign(alg: Algorithm, secret: &[u8], msg: &[u8]) -> Result<Vec<u8>, AlgorithmError> {
26    let _decision = crate::provider::require_provider(ProviderOperation::Sign, alg)?;
27    #[cfg(not(any(
28        feature = "ed25519",
29        feature = "p256",
30        feature = "p384",
31        feature = "p521",
32        feature = "secp256k1",
33        feature = "ml-dsa-44",
34        feature = "ml-dsa-65",
35        feature = "ml-dsa-87"
36    )))]
37    let _ = (secret, msg);
38
39    match alg {
40        Algorithm::Ed25519 => {
41            #[cfg(feature = "ed25519")]
42            {
43                crate::algorithms::ed25519::Ed25519Algo::sign(secret, msg)
44            }
45            #[cfg(not(feature = "ed25519"))]
46            {
47                Err(AlgorithmError::UnsupportedAlgorithm(alg))
48            }
49        }
50        Algorithm::P256 => {
51            #[cfg(feature = "p256")]
52            {
53                crate::algorithms::p256::P256Algo::sign(secret, msg)
54            }
55            #[cfg(not(feature = "p256"))]
56            {
57                Err(AlgorithmError::UnsupportedAlgorithm(alg))
58            }
59        }
60        Algorithm::P384 => {
61            #[cfg(feature = "p384")]
62            {
63                crate::algorithms::p384::P384Algo::sign(secret, msg)
64            }
65            #[cfg(not(feature = "p384"))]
66            {
67                Err(AlgorithmError::UnsupportedAlgorithm(alg))
68            }
69        }
70        Algorithm::P521 => {
71            #[cfg(feature = "p521")]
72            {
73                crate::algorithms::p521::P521Algo::sign(secret, msg)
74            }
75            #[cfg(not(feature = "p521"))]
76            {
77                Err(AlgorithmError::UnsupportedAlgorithm(alg))
78            }
79        }
80        Algorithm::Secp256k1 => {
81            #[cfg(feature = "secp256k1")]
82            {
83                crate::algorithms::secp256k1::Secp256k1Algo::sign(secret, msg)
84            }
85            #[cfg(not(feature = "secp256k1"))]
86            {
87                Err(AlgorithmError::UnsupportedAlgorithm(alg))
88            }
89        }
90        Algorithm::MlDsa44 => {
91            #[cfg(feature = "ml-dsa-44")]
92            {
93                crate::algorithms::ml_dsa_44::MlDsa44Algo::sign(secret, msg)
94            }
95            #[cfg(not(feature = "ml-dsa-44"))]
96            {
97                Err(AlgorithmError::UnsupportedAlgorithm(alg))
98            }
99        }
100        Algorithm::MlDsa65 => {
101            #[cfg(feature = "ml-dsa-65")]
102            {
103                crate::algorithms::ml_dsa_65::MlDsa65Algo::sign(secret, msg)
104            }
105            #[cfg(not(feature = "ml-dsa-65"))]
106            {
107                Err(AlgorithmError::UnsupportedAlgorithm(alg))
108            }
109        }
110        Algorithm::MlDsa87 => {
111            #[cfg(feature = "ml-dsa-87")]
112            {
113                crate::algorithms::ml_dsa_87::MlDsa87Algo::sign(secret, msg)
114            }
115            #[cfg(not(feature = "ml-dsa-87"))]
116            {
117                Err(AlgorithmError::UnsupportedAlgorithm(alg))
118            }
119        }
120        _ => Err(AlgorithmError::UnsupportedAlgorithm(alg)),
121    }
122}
123
124/// Verify a detached signature.
125///
126/// Fails closed: a signature that does not verify is an
127/// [`AlgorithmError::SignatureInvalid`] error, never a boolean, so a
128/// forgotten result check cannot be mistaken for success.
129///
130/// The crate README contains the compile-checked fail-closed verification
131/// example so test code remains separate from this production implementation.
132pub fn verify(alg: Algorithm, public: &[u8], msg: &[u8], sig: &[u8]) -> Result<(), AlgorithmError> {
133    let _decision = crate::provider::require_provider(ProviderOperation::Verify, alg)?;
134    #[cfg(not(any(
135        feature = "ed25519",
136        feature = "p256",
137        feature = "p384",
138        feature = "p521",
139        feature = "secp256k1",
140        feature = "ml-dsa-44",
141        feature = "ml-dsa-65",
142        feature = "ml-dsa-87"
143    )))]
144    let _ = (public, msg, sig);
145
146    match alg {
147        Algorithm::Ed25519 => {
148            #[cfg(feature = "ed25519")]
149            {
150                crate::algorithms::ed25519::Ed25519Algo::verify(public, msg, sig)
151            }
152            #[cfg(not(feature = "ed25519"))]
153            {
154                Err(AlgorithmError::UnsupportedAlgorithm(alg))
155            }
156        }
157        Algorithm::P256 => {
158            #[cfg(feature = "p256")]
159            {
160                crate::algorithms::p256::P256Algo::verify(public, msg, sig)
161            }
162            #[cfg(not(feature = "p256"))]
163            {
164                Err(AlgorithmError::UnsupportedAlgorithm(alg))
165            }
166        }
167        Algorithm::P384 => {
168            #[cfg(feature = "p384")]
169            {
170                crate::algorithms::p384::P384Algo::verify(public, msg, sig)
171            }
172            #[cfg(not(feature = "p384"))]
173            {
174                Err(AlgorithmError::UnsupportedAlgorithm(alg))
175            }
176        }
177        Algorithm::P521 => {
178            #[cfg(feature = "p521")]
179            {
180                crate::algorithms::p521::P521Algo::verify(public, msg, sig)
181            }
182            #[cfg(not(feature = "p521"))]
183            {
184                Err(AlgorithmError::UnsupportedAlgorithm(alg))
185            }
186        }
187        Algorithm::Secp256k1 => {
188            #[cfg(feature = "secp256k1")]
189            {
190                crate::algorithms::secp256k1::Secp256k1Algo::verify(public, msg, sig)
191            }
192            #[cfg(not(feature = "secp256k1"))]
193            {
194                Err(AlgorithmError::UnsupportedAlgorithm(alg))
195            }
196        }
197        Algorithm::MlDsa44 => {
198            #[cfg(feature = "ml-dsa-44")]
199            {
200                crate::algorithms::ml_dsa_44::MlDsa44Algo::verify(public, msg, sig)
201            }
202            #[cfg(not(feature = "ml-dsa-44"))]
203            {
204                Err(AlgorithmError::UnsupportedAlgorithm(alg))
205            }
206        }
207        Algorithm::MlDsa65 => {
208            #[cfg(feature = "ml-dsa-65")]
209            {
210                crate::algorithms::ml_dsa_65::MlDsa65Algo::verify(public, msg, sig)
211            }
212            #[cfg(not(feature = "ml-dsa-65"))]
213            {
214                Err(AlgorithmError::UnsupportedAlgorithm(alg))
215            }
216        }
217        Algorithm::MlDsa87 => {
218            #[cfg(feature = "ml-dsa-87")]
219            {
220                crate::algorithms::ml_dsa_87::MlDsa87Algo::verify(public, msg, sig)
221            }
222            #[cfg(not(feature = "ml-dsa-87"))]
223            {
224                Err(AlgorithmError::UnsupportedAlgorithm(alg))
225            }
226        }
227        _ => Err(AlgorithmError::UnsupportedAlgorithm(alg)),
228    }
229}