1use crate::{PqcError, Result};
5use async_trait::async_trait;
6use serde::{Deserialize, Serialize};
7use zeroize::Zeroize;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
11pub enum SignatureAlgorithm {
12 MlDsa44,
14 MlDsa65,
16 MlDsa87,
18 SlhDsa128s,
20 SlhDsa192s,
22 SlhDsa256s,
24 Ed25519,
26}
27
28impl SignatureAlgorithm {
29 pub fn public_key_size(&self) -> usize {
31 match self {
32 Self::MlDsa44 => 1312, Self::MlDsa65 => 1952, Self::MlDsa87 => 2592, Self::SlhDsa128s => 32, Self::SlhDsa192s => 48, Self::SlhDsa256s => 64, Self::Ed25519 => 32,
39 }
40 }
41
42 pub fn secret_key_size(&self) -> usize {
44 match self {
45 Self::MlDsa44 => 2560, Self::MlDsa65 => 4032, Self::MlDsa87 => 4896, Self::SlhDsa128s => 64, Self::SlhDsa192s => 96, Self::SlhDsa256s => 128, Self::Ed25519 => 32,
52 }
53 }
54
55 pub fn signature_size(&self) -> usize {
57 match self {
58 Self::MlDsa44 => 2420, Self::MlDsa65 => 3309, Self::MlDsa87 => 4627, Self::SlhDsa128s => 7856, Self::SlhDsa192s => 16224, Self::SlhDsa256s => 29792, Self::Ed25519 => 64,
65 }
66 }
67
68 #[cfg(feature = "ml-dsa")]
70 #[allow(dead_code)] pub(crate) fn to_saorsa_variant(&self) -> Option<saorsa_pqc::MlDsaVariant> {
72 match self {
73 Self::MlDsa44 => Some(saorsa_pqc::MlDsaVariant::MlDsa44),
74 Self::MlDsa65 => Some(saorsa_pqc::MlDsaVariant::MlDsa65),
75 Self::MlDsa87 => Some(saorsa_pqc::MlDsaVariant::MlDsa87),
76 _ => None,
77 }
78 }
79}
80
81impl Default for SignatureAlgorithm {
82 fn default() -> Self {
83 Self::MlDsa65 }
85}
86
87#[derive(Clone, Serialize, Deserialize)]
89pub struct VerifyingKey {
90 pub algorithm: SignatureAlgorithm,
91 pub key_bytes: Vec<u8>,
92}
93
94#[derive(Clone)]
96pub struct SigningKey {
97 pub algorithm: SignatureAlgorithm,
98 pub key_bytes: Vec<u8>,
99}
100
101impl Drop for SigningKey {
102 fn drop(&mut self) {
103 self.key_bytes.zeroize();
104 }
105}
106
107#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct DigitalSignature {
110 pub algorithm: SignatureAlgorithm,
111 pub signature_bytes: Vec<u8>,
112}
113
114#[async_trait]
116pub trait Signature: Send + Sync {
117 async fn generate_keypair(&self, alg: SignatureAlgorithm)
119 -> Result<(VerifyingKey, SigningKey)>;
120
121 async fn sign(&self, key: &SigningKey, message: &[u8]) -> Result<DigitalSignature>;
123
124 async fn verify(
126 &self,
127 key: &VerifyingKey,
128 message: &[u8],
129 signature: &DigitalSignature,
130 ) -> Result<bool>;
131}
132
133#[cfg(feature = "ml-dsa")]
135pub struct MlDsa {
136 _phantom: std::marker::PhantomData<()>,
137}
138
139#[cfg(feature = "ml-dsa")]
140impl MlDsa {
141 pub fn new() -> Self {
142 Self {
143 _phantom: std::marker::PhantomData,
144 }
145 }
146}
147
148#[cfg(feature = "ml-dsa")]
149#[async_trait]
150impl Signature for MlDsa {
151 async fn generate_keypair(
152 &self,
153 alg: SignatureAlgorithm,
154 ) -> Result<(VerifyingKey, SigningKey)> {
155 use saorsa_pqc::{MlDsa65, MlDsaOperations};
156
157 if !matches!(
158 alg,
159 SignatureAlgorithm::MlDsa44 | SignatureAlgorithm::MlDsa65 | SignatureAlgorithm::MlDsa87
160 ) {
161 return Err(PqcError::UnsupportedAlgorithm(format!(
162 "{:?} not supported",
163 alg
164 )));
165 }
166
167 let ml_dsa = MlDsa65::new();
170 let (pub_key, sec_key) = ml_dsa
171 .generate_keypair()
172 .map_err(|e| PqcError::SignatureError(format!("Keypair generation failed: {:?}", e)))?;
173
174 Ok((
175 VerifyingKey {
176 algorithm: alg,
177 key_bytes: pub_key.as_bytes().to_vec(),
178 },
179 SigningKey {
180 algorithm: alg,
181 key_bytes: sec_key.as_bytes().to_vec(),
182 },
183 ))
184 }
185
186 async fn sign(&self, key: &SigningKey, message: &[u8]) -> Result<DigitalSignature> {
187 use saorsa_pqc::{MlDsa65, MlDsaOperations, MlDsaSecretKey};
188
189 let ml_dsa = MlDsa65::new();
190 let sec_key = MlDsaSecretKey::from_bytes(&key.key_bytes)
191 .map_err(|e| PqcError::SignatureError(format!("Invalid signing key: {:?}", e)))?;
192
193 let signature = ml_dsa
194 .sign(&sec_key, message)
195 .map_err(|e| PqcError::SignatureError(format!("Signing failed: {:?}", e)))?;
196
197 Ok(DigitalSignature {
198 algorithm: key.algorithm,
199 signature_bytes: signature.as_bytes().to_vec(),
200 })
201 }
202
203 async fn verify(
204 &self,
205 key: &VerifyingKey,
206 message: &[u8],
207 signature: &DigitalSignature,
208 ) -> Result<bool> {
209 use saorsa_pqc::{MlDsa65, MlDsaOperations, MlDsaPublicKey, MlDsaSignature};
210
211 if key.algorithm != signature.algorithm {
212 return Ok(false);
213 }
214
215 let ml_dsa = MlDsa65::new();
216 let pub_key = MlDsaPublicKey::from_bytes(&key.key_bytes)
217 .map_err(|e| PqcError::SignatureError(format!("Invalid verifying key: {:?}", e)))?;
218
219 let sig = MlDsaSignature::from_bytes(&signature.signature_bytes)
220 .map_err(|e| PqcError::SignatureError(format!("Invalid signature: {:?}", e)))?;
221
222 Ok(ml_dsa.verify(&pub_key, message, &sig).is_ok())
223 }
224}
225
226pub struct Ed25519Sig;
228
229#[async_trait]
230impl Signature for Ed25519Sig {
231 async fn generate_keypair(
232 &self,
233 alg: SignatureAlgorithm,
234 ) -> Result<(VerifyingKey, SigningKey)> {
235 if !matches!(alg, SignatureAlgorithm::Ed25519) {
236 return Err(PqcError::UnsupportedAlgorithm(
237 "Use MlDsa for ML-DSA".into(),
238 ));
239 }
240
241 use ed25519_dalek::SigningKey as Ed25519SigningKey;
242 use rand::{rngs::OsRng, Rng};
243
244 let mut csprng = OsRng;
245 let mut secret_bytes = [0u8; 32];
246 csprng.fill(&mut secret_bytes);
247
248 let signing_key = Ed25519SigningKey::from_bytes(&secret_bytes);
249 let verifying_key = signing_key.verifying_key();
250
251 Ok((
252 VerifyingKey {
253 algorithm: alg,
254 key_bytes: verifying_key.as_bytes().to_vec(),
255 },
256 SigningKey {
257 algorithm: alg,
258 key_bytes: signing_key.as_bytes().to_vec(),
259 },
260 ))
261 }
262
263 async fn sign(&self, key: &SigningKey, message: &[u8]) -> Result<DigitalSignature> {
264 use ed25519_dalek::{Signer, SigningKey as Ed25519SigningKey};
265
266 let mut sk_bytes = [0u8; 32];
267 sk_bytes.copy_from_slice(&key.key_bytes);
268 let signing_key = Ed25519SigningKey::from_bytes(&sk_bytes);
269
270 let signature = signing_key.sign(message);
271
272 Ok(DigitalSignature {
273 algorithm: key.algorithm,
274 signature_bytes: signature.to_bytes().to_vec(),
275 })
276 }
277
278 async fn verify(
279 &self,
280 key: &VerifyingKey,
281 message: &[u8],
282 signature: &DigitalSignature,
283 ) -> Result<bool> {
284 use ed25519_dalek::{
285 Signature as Ed25519Signature, Verifier, VerifyingKey as Ed25519VerifyingKey,
286 };
287
288 let mut vk_bytes = [0u8; 32];
289 vk_bytes.copy_from_slice(&key.key_bytes);
290 let verifying_key = Ed25519VerifyingKey::from_bytes(&vk_bytes)
291 .map_err(|e| PqcError::SignatureError(format!("Invalid verifying key: {}", e)))?;
292
293 let mut sig_bytes = [0u8; 64];
294 sig_bytes.copy_from_slice(&signature.signature_bytes);
295 let sig = Ed25519Signature::from_bytes(&sig_bytes);
296
297 Ok(verifying_key.verify(message, &sig).is_ok())
298 }
299}
300
301#[cfg(test)]
302mod tests {
303 use super::*;
304
305 #[tokio::test]
306 #[cfg(feature = "ml-dsa")]
307 async fn test_ml_dsa_65() {
308 let signer = MlDsa::new();
309 let (vk, sk) = signer
310 .generate_keypair(SignatureAlgorithm::MlDsa65)
311 .await
312 .unwrap();
313
314 let message = b"Test message for ML-DSA-65";
315 let signature = signer.sign(&sk, message).await.unwrap();
316
317 assert!(signer.verify(&vk, message, &signature).await.unwrap());
318 assert_eq!(signature.signature_bytes.len(), 3309); }
326
327 #[tokio::test]
328 async fn test_ed25519() {
329 let signer = Ed25519Sig;
330 let (vk, sk) = signer
331 .generate_keypair(SignatureAlgorithm::Ed25519)
332 .await
333 .unwrap();
334
335 let message = b"Test message for Ed25519";
336 let signature = signer.sign(&sk, message).await.unwrap();
337
338 assert!(signer.verify(&vk, message, &signature).await.unwrap());
339 }
340}