1#![allow(non_snake_case)]
19
20use std::sync::Arc;
49use crate::core::{RiResult, RiError};
50
51#[derive(Debug, Clone)]
52#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
53pub struct FalconPublicKey(pub Vec<u8>);
54
55#[derive(Debug, Clone)]
56#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
57pub struct FalconSecretKey(pub Vec<u8>);
58
59#[derive(Debug, Clone)]
60#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
61pub struct FalconSignature(pub Vec<u8>);
62
63#[derive(Debug, Clone)]
64#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
65pub struct FalconSigner {
66 algorithm: Arc<std::sync::RwLock<FalconAlgorithm>>,
67}
68
69#[derive(Debug, Clone, Copy)]
70enum FalconAlgorithm {
71 Falcon512,
72 Falcon1024,
73}
74
75impl FalconSigner {
76 pub fn new() -> Self {
77 Self {
78 algorithm: Arc::new(std::sync::RwLock::new(FalconAlgorithm::Falcon512)),
79 }
80 }
81
82 pub fn with_algorithm(algorithm: super::RiPostQuantumAlgorithm) -> Self {
83 let algo = match algorithm {
84 super::RiPostQuantumAlgorithm::Falcon512 => FalconAlgorithm::Falcon512,
85 super::RiPostQuantumAlgorithm::Falcon1024 => FalconAlgorithm::Falcon1024,
86 _ => FalconAlgorithm::Falcon512,
87 };
88 Self {
89 algorithm: Arc::new(std::sync::RwLock::new(algo)),
90 }
91 }
92
93 #[cfg(feature = "protocol")]
94 pub fn keygen(&self) -> RiResult<(Vec<u8>, Vec<u8>)> {
95 use oqs::sig::Sig;
96
97 let algo = *self.algorithm.read().map_err(|e|
98 RiError::InvalidState(format!("Lock error: {}", e))
99 )?;
100 let sig = match algo {
101 FalconAlgorithm::Falcon512 => Sig::new(oqs::sig::Algorithm::Falcon512),
102 FalconAlgorithm::Falcon1024 => Sig::new(oqs::sig::Algorithm::Falcon1024),
103 }.map_err(|e| RiError::Other(format!("Failed to initialize Falcon: {:?}", e)))?;
104
105 let (pk, sk) = sig.keypair()
106 .map_err(|e| RiError::Other(format!("Falcon keygen failed: {:?}", e)))?;
107 Ok((pk.into_vec(), sk.into_vec()))
108 }
109
110 #[cfg(not(feature = "protocol"))]
111 pub fn keygen(&self) -> RiResult<(Vec<u8>, Vec<u8>)> {
112 Err(RiError::Other(
113 "Post-quantum cryptography requires the 'protocol' feature. \
114 Enable with: cargo build --features protocol".to_string()
115 ))
116 }
117
118 #[cfg(feature = "protocol")]
119 pub fn sign(&self, secret_key: &[u8], message: &[u8]) -> RiResult<Vec<u8>> {
120 use oqs::sig::Sig;
121
122 let algo = *self.algorithm.read().map_err(|e|
123 RiError::InvalidState(format!("Lock error: {}", e))
124 )?;
125 let sig = match algo {
126 FalconAlgorithm::Falcon512 => Sig::new(oqs::sig::Algorithm::Falcon512),
127 FalconAlgorithm::Falcon1024 => Sig::new(oqs::sig::Algorithm::Falcon1024),
128 }.map_err(|e| RiError::Other(format!("Failed to initialize Falcon: {:?}", e)))?;
129
130 let sk = sig.secret_key_from_bytes(secret_key)
131 .ok_or_else(|| RiError::Other("Invalid secret key".to_string()))?;
132 let signature = sig.sign(message, &sk)
133 .map_err(|e| RiError::Other(format!("Falcon sign failed: {:?}", e)))?;
134 Ok(signature.into_vec())
135 }
136
137 #[cfg(not(feature = "protocol"))]
138 pub fn sign(&self, _secret_key: &[u8], _message: &[u8]) -> RiResult<Vec<u8>> {
139 Err(RiError::Other(
140 "Post-quantum cryptography requires the 'protocol' feature. \
141 Enable with: cargo build --features protocol".to_string()
142 ))
143 }
144
145 #[cfg(feature = "protocol")]
146 pub fn verify(&self, public_key: &[u8], message: &[u8], signature: &[u8]) -> RiResult<bool> {
147 use oqs::sig::Sig;
148
149 let algo = *self.algorithm.read().map_err(|e|
150 RiError::InvalidState(format!("Lock error: {}", e))
151 )?;
152 let sig = match algo {
153 FalconAlgorithm::Falcon512 => Sig::new(oqs::sig::Algorithm::Falcon512),
154 FalconAlgorithm::Falcon1024 => Sig::new(oqs::sig::Algorithm::Falcon1024),
155 }.map_err(|e| RiError::Other(format!("Failed to initialize Falcon: {:?}", e)))?;
156
157 let pk = sig.public_key_from_bytes(public_key)
158 .ok_or_else(|| RiError::Other("Invalid public key".to_string()))?;
159 let sig_bytes = sig.signature_from_bytes(signature)
160 .ok_or_else(|| RiError::Other("Invalid signature".to_string()))?;
161 let result = sig.verify(message, &sig_bytes, &pk);
162 Ok(result.is_ok())
163 }
164
165 #[cfg(not(feature = "protocol"))]
166 pub fn verify(&self, _public_key: &[u8], _message: &[u8], _signature: &[u8]) -> RiResult<bool> {
167 Err(RiError::Other(
168 "Post-quantum cryptography requires the 'protocol' feature. \
169 Enable with: cargo build --features protocol".to_string()
170 ))
171 }
172}
173
174impl Default for FalconSigner {
175 fn default() -> Self {
176 Self::new()
177 }
178}
179
180#[cfg(feature = "pyo3")]
181#[pyo3::prelude::pymethods]
182impl FalconSigner {
183 #[new]
184 pub fn new_py() -> Self {
185 Self::new()
186 }
187
188 pub fn keygen_py(&self) -> Option<(Vec<u8>, Vec<u8>)> {
189 self.keygen().ok()
190 }
191
192 pub fn sign_py(&self, secret_key: &[u8], message: &[u8]) -> Option<Vec<u8>> {
193 self.sign(secret_key, message).ok()
194 }
195
196 pub fn verify_py(&self, public_key: &[u8], message: &[u8], signature: &[u8]) -> bool {
197 self.verify(public_key, message, signature).unwrap_or(false)
198 }
199}