use crate::error::{QVError, QVResult};
use pqcrypto_traits::sign::{
DetachedSignature as _, PublicKey as _, SecretKey as _, VerificationError,
};
pub mod falcon512 {
use super::*;
use pqcrypto_falcon::falcon512 as ffi;
pub const MAX_SIG_BYTES: usize = 666;
pub const VK_BYTES: usize = 897;
pub const SK_BYTES: usize = 1281;
#[derive(Clone)]
pub struct QVFalcon512SigningKey(ffi::SecretKey);
#[derive(Clone)]
pub struct QVFalcon512VerifyingKey(ffi::PublicKey);
impl QVFalcon512SigningKey {
pub fn to_bytes(&self) -> Vec<u8> {
self.0.as_bytes().to_vec()
}
pub fn from_bytes(bytes: &[u8]) -> QVResult<Self> {
ffi::SecretKey::from_bytes(bytes)
.map(Self)
.map_err(|_| QVError::SerializationError("Falcon-512 sk".into()))
}
}
impl QVFalcon512VerifyingKey {
pub fn to_bytes(&self) -> Vec<u8> {
self.0.as_bytes().to_vec()
}
pub fn from_bytes(bytes: &[u8]) -> QVResult<Self> {
ffi::PublicKey::from_bytes(bytes)
.map(Self)
.map_err(|_| QVError::SerializationError("Falcon-512 vk".into()))
}
}
pub fn generate_keypair() -> QVResult<(QVFalcon512SigningKey, QVFalcon512VerifyingKey)> {
let (pk, sk) = ffi::keypair();
Ok((QVFalcon512SigningKey(sk), QVFalcon512VerifyingKey(pk)))
}
pub fn sign(sk: &QVFalcon512SigningKey, msg: &[u8]) -> QVResult<Vec<u8>> {
let sig = ffi::detached_sign(msg, &sk.0);
Ok(sig.as_bytes().to_vec())
}
pub fn verify(vk: &QVFalcon512VerifyingKey, msg: &[u8], sig: &[u8]) -> QVResult<()> {
let parsed = ffi::DetachedSignature::from_bytes(sig)
.map_err(|_| QVError::SignatureInvalid)?;
match ffi::verify_detached_signature(&parsed, msg, &vk.0) {
Ok(()) => Ok(()),
Err(VerificationError::InvalidSignature) => Err(QVError::SignatureInvalid),
Err(_) => Err(QVError::SignatureInvalid),
}
}
}
pub mod falcon1024 {
use super::*;
use pqcrypto_falcon::falcon1024 as ffi;
pub const MAX_SIG_BYTES: usize = 1280;
pub const VK_BYTES: usize = 1793;
pub const SK_BYTES: usize = 2305;
#[derive(Clone)]
pub struct QVFalcon1024SigningKey(ffi::SecretKey);
#[derive(Clone)]
pub struct QVFalcon1024VerifyingKey(ffi::PublicKey);
impl QVFalcon1024SigningKey {
pub fn to_bytes(&self) -> Vec<u8> {
self.0.as_bytes().to_vec()
}
pub fn from_bytes(bytes: &[u8]) -> QVResult<Self> {
ffi::SecretKey::from_bytes(bytes)
.map(Self)
.map_err(|_| QVError::SerializationError("Falcon-1024 sk".into()))
}
}
impl QVFalcon1024VerifyingKey {
pub fn to_bytes(&self) -> Vec<u8> {
self.0.as_bytes().to_vec()
}
pub fn from_bytes(bytes: &[u8]) -> QVResult<Self> {
ffi::PublicKey::from_bytes(bytes)
.map(Self)
.map_err(|_| QVError::SerializationError("Falcon-1024 vk".into()))
}
}
pub fn generate_keypair() -> QVResult<(QVFalcon1024SigningKey, QVFalcon1024VerifyingKey)> {
let (pk, sk) = ffi::keypair();
Ok((QVFalcon1024SigningKey(sk), QVFalcon1024VerifyingKey(pk)))
}
pub fn sign(sk: &QVFalcon1024SigningKey, msg: &[u8]) -> QVResult<Vec<u8>> {
let sig = ffi::detached_sign(msg, &sk.0);
Ok(sig.as_bytes().to_vec())
}
pub fn verify(vk: &QVFalcon1024VerifyingKey, msg: &[u8], sig: &[u8]) -> QVResult<()> {
let parsed = ffi::DetachedSignature::from_bytes(sig)
.map_err(|_| QVError::SignatureInvalid)?;
match ffi::verify_detached_signature(&parsed, msg, &vk.0) {
Ok(()) => Ok(()),
Err(VerificationError::InvalidSignature) => Err(QVError::SignatureInvalid),
Err(_) => Err(QVError::SignatureInvalid),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn falcon512_roundtrip() {
let (sk, vk) = falcon512::generate_keypair().expect("keygen");
let msg = b"QuantumVault v4.1 Falcon-512 roundtrip";
let sig = falcon512::sign(&sk, msg).expect("sign");
assert!(sig.len() <= falcon512::MAX_SIG_BYTES, "sig {} > max", sig.len());
assert!(sig.len() > 500, "sig suspiciously small: {}", sig.len());
falcon512::verify(&vk, msg, &sig).expect("verify");
let mut bad = sig.clone();
bad[10] ^= 0xFF;
assert!(falcon512::verify(&vk, msg, &bad).is_err());
let vk_bytes = vk.to_bytes();
assert_eq!(vk_bytes.len(), falcon512::VK_BYTES);
let vk2 = falcon512::QVFalcon512VerifyingKey::from_bytes(&vk_bytes).expect("vk parse");
falcon512::verify(&vk2, msg, &sig).expect("verify after reparse");
}
#[test]
fn falcon1024_roundtrip() {
let (sk, vk) = falcon1024::generate_keypair().expect("keygen");
let msg = b"QuantumVault v4.1 Falcon-1024 roundtrip";
let sig = falcon1024::sign(&sk, msg).expect("sign");
assert!(sig.len() <= falcon1024::MAX_SIG_BYTES, "sig {} > max", sig.len());
assert!(sig.len() > 1000, "sig suspiciously small: {}", sig.len());
falcon1024::verify(&vk, msg, &sig).expect("verify");
let sk_bytes = sk.to_bytes();
assert_eq!(sk_bytes.len(), falcon1024::SK_BYTES);
}
#[test]
fn size_advantage_vs_mldsa87() {
let (sk, _vk) = falcon512::generate_keypair().expect("keygen");
let sig = falcon512::sign(&sk, b"size demo").expect("sign");
assert!(sig.len() < 4627 / 5, "expected at least 5x smaller than ML-DSA-87");
}
}