#![allow(non_snake_case)]
use std::sync::Arc;
use crate::core::{RiResult, RiError};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub struct FalconPublicKey(pub Vec<u8>);
#[derive(Debug, Clone)]
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub struct FalconSecretKey(pub Vec<u8>);
#[derive(Debug, Clone)]
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub struct FalconSignature(pub Vec<u8>);
#[derive(Debug, Clone)]
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub struct FalconSigner {
algorithm: Arc<std::sync::RwLock<FalconAlgorithm>>,
}
#[derive(Debug, Clone, Copy)]
enum FalconAlgorithm {
Falcon512,
Falcon1024,
}
impl FalconSigner {
pub fn new() -> Self {
Self {
algorithm: Arc::new(std::sync::RwLock::new(FalconAlgorithm::Falcon512)),
}
}
pub fn with_algorithm(algorithm: super::RiPostQuantumAlgorithm) -> Self {
let algo = match algorithm {
super::RiPostQuantumAlgorithm::Falcon512 => FalconAlgorithm::Falcon512,
super::RiPostQuantumAlgorithm::Falcon1024 => FalconAlgorithm::Falcon1024,
_ => FalconAlgorithm::Falcon512,
};
Self {
algorithm: Arc::new(std::sync::RwLock::new(algo)),
}
}
#[cfg(feature = "protocol")]
pub fn keygen(&self) -> RiResult<(Vec<u8>, Vec<u8>)> {
use oqs::sig::Sig;
let algo = *self.algorithm.read().map_err(|e|
RiError::InvalidState(format!("Lock error: {}", e))
)?;
let sig = match algo {
FalconAlgorithm::Falcon512 => Sig::new(oqs::sig::Algorithm::Falcon512),
FalconAlgorithm::Falcon1024 => Sig::new(oqs::sig::Algorithm::Falcon1024),
}.map_err(|e| RiError::Other(format!("Failed to initialize Falcon: {:?}", e)))?;
let (pk, sk) = sig.keypair()
.map_err(|e| RiError::Other(format!("Falcon keygen failed: {:?}", e)))?;
Ok((pk.into_vec(), sk.into_vec()))
}
#[cfg(not(feature = "protocol"))]
pub fn keygen(&self) -> RiResult<(Vec<u8>, Vec<u8>)> {
Err(RiError::Other(
"Post-quantum cryptography requires the 'protocol' feature. \
Enable with: cargo build --features protocol".to_string()
))
}
#[cfg(feature = "protocol")]
pub fn sign(&self, secret_key: &[u8], message: &[u8]) -> RiResult<Vec<u8>> {
use oqs::sig::Sig;
let algo = *self.algorithm.read().map_err(|e|
RiError::InvalidState(format!("Lock error: {}", e))
)?;
let sig = match algo {
FalconAlgorithm::Falcon512 => Sig::new(oqs::sig::Algorithm::Falcon512),
FalconAlgorithm::Falcon1024 => Sig::new(oqs::sig::Algorithm::Falcon1024),
}.map_err(|e| RiError::Other(format!("Failed to initialize Falcon: {:?}", e)))?;
let sk = sig.secret_key_from_bytes(secret_key)
.ok_or_else(|| RiError::Other("Invalid secret key".to_string()))?;
let signature = sig.sign(message, &sk)
.map_err(|e| RiError::Other(format!("Falcon sign failed: {:?}", e)))?;
Ok(signature.into_vec())
}
#[cfg(not(feature = "protocol"))]
pub fn sign(&self, _secret_key: &[u8], _message: &[u8]) -> RiResult<Vec<u8>> {
Err(RiError::Other(
"Post-quantum cryptography requires the 'protocol' feature. \
Enable with: cargo build --features protocol".to_string()
))
}
#[cfg(feature = "protocol")]
pub fn verify(&self, public_key: &[u8], message: &[u8], signature: &[u8]) -> RiResult<bool> {
use oqs::sig::Sig;
let algo = *self.algorithm.read().map_err(|e|
RiError::InvalidState(format!("Lock error: {}", e))
)?;
let sig = match algo {
FalconAlgorithm::Falcon512 => Sig::new(oqs::sig::Algorithm::Falcon512),
FalconAlgorithm::Falcon1024 => Sig::new(oqs::sig::Algorithm::Falcon1024),
}.map_err(|e| RiError::Other(format!("Failed to initialize Falcon: {:?}", e)))?;
let pk = sig.public_key_from_bytes(public_key)
.ok_or_else(|| RiError::Other("Invalid public key".to_string()))?;
let sig_bytes = sig.signature_from_bytes(signature)
.ok_or_else(|| RiError::Other("Invalid signature".to_string()))?;
let result = sig.verify(message, &sig_bytes, &pk);
Ok(result.is_ok())
}
#[cfg(not(feature = "protocol"))]
pub fn verify(&self, _public_key: &[u8], _message: &[u8], _signature: &[u8]) -> RiResult<bool> {
Err(RiError::Other(
"Post-quantum cryptography requires the 'protocol' feature. \
Enable with: cargo build --features protocol".to_string()
))
}
}
impl Default for FalconSigner {
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "pyo3")]
#[pyo3::prelude::pymethods]
impl FalconSigner {
#[new]
pub fn new_py() -> Self {
Self::new()
}
pub fn keygen_py(&self) -> Option<(Vec<u8>, Vec<u8>)> {
self.keygen().ok()
}
pub fn sign_py(&self, secret_key: &[u8], message: &[u8]) -> Option<Vec<u8>> {
self.sign(secret_key, message).ok()
}
pub fn verify_py(&self, public_key: &[u8], message: &[u8], signature: &[u8]) -> bool {
self.verify(public_key, message, signature).unwrap_or(false)
}
}