1use pqcrypto_mldsa::mldsa87;
4use pqcrypto_traits::sign::{DetachedSignature as _, PublicKey as _};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct PQSignature {
11 pub signature: Vec<u8>,
13 pub public_key: Vec<u8>,
15 pub algorithm: String,
17}
18
19pub struct PQKeyPair {
21 pub public_key: mldsa87::PublicKey,
22 pub secret_key: mldsa87::SecretKey,
23}
24
25impl PQKeyPair {
26 pub fn generate() -> Self {
28 let (pk, sk) = mldsa87::keypair();
29 PQKeyPair {
30 public_key: pk,
31 secret_key: sk,
32 }
33 }
34
35 pub fn sign(&self, message: &[u8]) -> PQSignature {
37 let sig = mldsa87::detached_sign(message, &self.secret_key);
38
39 PQSignature {
40 signature: sig.as_bytes().to_vec(),
41 public_key: self.public_key.as_bytes().to_vec(),
42 algorithm: "ML-DSA-87".to_string(),
43 }
44 }
45}
46
47impl PQSignature {
48 pub fn verify(&self, message: &[u8]) -> Result<(), String> {
50 let pk =
52 mldsa87::PublicKey::from_bytes(&self.public_key).map_err(|_| "Invalid public key")?;
53
54 let sig = mldsa87::DetachedSignature::from_bytes(&self.signature)
56 .map_err(|_| "Invalid signature")?;
57
58 mldsa87::verify_detached_signature(&sig, message, &pk)
60 .map_err(|_| "Signature verification failed".to_string())
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn test_pq_signature() {
70 let keypair = PQKeyPair::generate();
71 let message = b"Test commit message";
72
73 let signature = keypair.sign(message);
74 assert!(signature.verify(message).is_ok());
75
76 let wrong_message = b"Wrong message";
78 assert!(signature.verify(wrong_message).is_err());
79 }
80}