1use ml_dsa::{MlDsa87, EncodedVerifyingKey, KeyGen};
2use ml_dsa::signature::{Signer, Verifier};
3use rand::rngs::OsRng;
4use sha3::{Sha3_256, Digest};
5use zeroize::Zeroizing;
6use crate::error::{QVError, QVResult};
7
8pub const SIG_LEN: usize = 4627;
10pub const VK_LEN: usize = 2592;
12pub const SEED_LEN: usize = 32;
14
15pub struct QVSigningKey {
19 inner: ml_dsa::SigningKey<MlDsa87>,
20}
21
22pub struct QVVerifyingKey {
24 inner: ml_dsa::VerifyingKey<MlDsa87>,
25}
26
27impl QVSigningKey {
28 pub fn from_bytes(seed: &[u8]) -> QVResult<Self> {
30 if seed.len() != SEED_LEN {
31 return Err(QVError::KeyGenFailed);
32 }
33 let arr: ml_dsa::B32 = seed.try_into().map_err(|_| QVError::KeyGenFailed)?;
34 Ok(QVSigningKey { inner: MlDsa87::from_seed(&arr) })
35 }
36
37 pub fn to_bytes(&self) -> Zeroizing<Vec<u8>> {
39 Zeroizing::new(self.inner.to_seed().to_vec())
40 }
41}
42
43impl QVVerifyingKey {
44 pub fn from_bytes(bytes: &[u8]) -> QVResult<Self> {
46 let arr = EncodedVerifyingKey::<MlDsa87>::try_from(bytes)
47 .map_err(|_| QVError::KeyGenFailed)?;
48 Ok(QVVerifyingKey { inner: ml_dsa::VerifyingKey::decode(&arr) })
49 }
50
51 pub fn to_bytes(&self) -> Vec<u8> {
53 self.inner.encode().to_vec()
54 }
55}
56
57pub fn generate_keypair() -> QVResult<(QVSigningKey, QVVerifyingKey)> {
65 use rand::RngCore;
66 let mut seed_bytes = [0u8; 32];
67 OsRng.fill_bytes(&mut seed_bytes);
68 let seed: ml_dsa::B32 = seed_bytes.into();
69 let sk_inner = MlDsa87::from_seed(&seed);
70 let vk_inner = ml_dsa::signature::Keypair::verifying_key(&sk_inner);
71 Ok((QVSigningKey { inner: sk_inner }, QVVerifyingKey { inner: vk_inner }))
72}
73
74pub fn sign(sk: &QVSigningKey, message: &[u8]) -> QVResult<Vec<u8>> {
76 let sig: ml_dsa::Signature<MlDsa87> = sk.inner.try_sign(message)
77 .map_err(|_| QVError::SignatureInvalid)?;
78 Ok(sig.encode().to_vec())
79}
80
81pub fn verify(vk: &QVVerifyingKey, message: &[u8], signature_bytes: &[u8]) -> QVResult<()> {
83 let sig = ml_dsa::Signature::<MlDsa87>::try_from(signature_bytes)
84 .map_err(|_| QVError::SignatureInvalid)?;
85 vk.inner.verify(message, &sig).map_err(|_| QVError::SignatureInvalid)
86}
87
88pub fn sha3_256(data: &[u8]) -> [u8; 32] {
90 let mut h = Sha3_256::new();
91 h.update(data);
92 h.finalize().into()
93}