1pub mod algorithms;
22pub mod bridge;
23pub mod compression;
24pub mod errors;
25pub mod simple;
26pub mod types;
27
28pub use bridge::*;
29pub use errors::*;
30pub use types::*;
31
32pub use simple::qurox;
33pub use simple::{HybridSigner, HybridVerifier, QuantumEncryptor, QuantumSigner, QuantumVerifier};
34pub use algorithms::ecdsa::EcdsaCurve;
35
36use algorithms::*;
37use compression::*;
38
39pub struct QuroxCrypto;
40
41impl QuroxCrypto {
42 pub fn generate_ecdsa_keypair(curve: EcdsaCurve) -> Result<KeyPair> {
43 EcdsaCrypto::generate_keypair(curve)
44 }
45
46 pub fn generate_schnorr_keypair() -> Result<KeyPair> {
47 SchnorrCrypto::generate_keypair()
48 }
49
50 pub fn generate_mldsa_keypair() -> Result<KeyPair> {
51 MlDsaCrypto::generate_keypair()
52 }
53
54 pub fn generate_slh_dsa_keypair() -> Result<KeyPair> {
55 SlhDsaCrypto::generate_keypair()
56 }
57
58 pub fn generate_mlkem_keypair() -> Result<KeyPair> {
59 MlKemCrypto::generate_keypair()
60 }
61
62 pub fn sign(private_key: &PrivateKey, message: &[u8]) -> Result<Signature> {
63 match private_key.algorithm {
64 Algorithm::EcdsaK256 | Algorithm::EcdsaP256 => EcdsaCrypto::sign(private_key, message),
65 Algorithm::Schnorr => SchnorrCrypto::sign(private_key, message),
66 Algorithm::MlDsa44 => MlDsaCrypto::sign(private_key, message),
67 Algorithm::SlhDsaSha2128f => SlhDsaCrypto::sign(private_key, message),
68 Algorithm::MlKem768 => Err(CryptoError::Generic(
69 "ML-KEM is for encryption, not signing".to_string(),
70 )),
71 Algorithm::Hybrid => Err(CryptoError::Generic(
72 "Use sign_hybrid for hybrid signatures".to_string(),
73 )),
74 }
75 }
76
77 pub fn verify(public_key: &PublicKey, message: &[u8], signature: &Signature) -> Result<bool> {
78 match public_key.algorithm {
79 Algorithm::EcdsaK256 | Algorithm::EcdsaP256 => {
80 EcdsaCrypto::verify(public_key, message, signature)
81 }
82 Algorithm::Schnorr => SchnorrCrypto::verify(public_key, message, signature),
83 Algorithm::MlDsa44 => MlDsaCrypto::verify(public_key, message, signature),
84 Algorithm::SlhDsaSha2128f => SlhDsaCrypto::verify(public_key, message, signature),
85 Algorithm::MlKem768 => Err(CryptoError::Generic(
86 "ML-KEM is for encryption, not signing".to_string(),
87 )),
88 Algorithm::Hybrid => Err(CryptoError::Generic(
89 "Use verify_hybrid for hybrid signatures".to_string(),
90 )),
91 }
92 }
93
94 pub fn encapsulate(public_key: &PublicKey) -> Result<EncryptionResult> {
95 match public_key.algorithm {
96 Algorithm::MlKem768 => MlKemCrypto::encapsulate(public_key),
97 _ => Err(CryptoError::Generic(
98 "Algorithm does not support encapsulation".to_string(),
99 )),
100 }
101 }
102
103 pub fn decapsulate(
104 private_key: &PrivateKey,
105 ciphertext: &[u8],
106 ) -> Result<zeroize::Zeroizing<Vec<u8>>> {
107 match private_key.algorithm {
108 Algorithm::MlKem768 => MlKemCrypto::decapsulate(private_key, ciphertext),
109 _ => Err(CryptoError::Generic(
110 "Algorithm does not support decapsulation".to_string(),
111 )),
112 }
113 }
114
115 pub fn create_hybrid_crypto(policy: HybridPolicy) -> HybridCrypto {
116 HybridCrypto::new(policy)
117 }
118
119 pub fn create_hybrid_crypto_default() -> HybridCrypto {
120 HybridCrypto::new_default()
121 }
122
123 pub fn generate_hybrid_keypair(hybrid_crypto: &HybridCrypto) -> Result<HybridKeyPair> {
124 hybrid_crypto.generate_hybrid_keypair()
125 }
126
127 pub fn sign_hybrid(
128 hybrid_crypto: &HybridCrypto,
129 hybrid_keypair: &HybridKeyPair,
130 message: &[u8],
131 ) -> Result<HybridSignature> {
132 hybrid_crypto.sign_hybrid(hybrid_keypair, message)
133 }
134
135 pub fn verify_hybrid(
136 hybrid_crypto: &HybridCrypto,
137 hybrid_keypair: &HybridKeyPair,
138 message: &[u8],
139 signature: &HybridSignature,
140 ) -> Result<bool> {
141 hybrid_crypto.verify_hybrid(hybrid_keypair, message, signature)
142 }
143
144 pub fn create_compression_engine(config: CompressionConfig) -> CompressionEngine {
145 CompressionEngine::new(config)
146 }
147
148 pub fn create_compression_engine_default() -> CompressionEngine {
149 CompressionEngine::new_default()
150 }
151
152 pub fn compress_hybrid_signature(
153 hybrid_crypto: &HybridCrypto,
154 signature: &HybridSignature,
155 ) -> Result<CompressedHybridSignature> {
156 hybrid_crypto.compress_signature(signature)
157 }
158
159 pub fn decompress_hybrid_signature(
160 hybrid_crypto: &HybridCrypto,
161 compressed: &CompressedHybridSignature,
162 ) -> Result<HybridSignature> {
163 hybrid_crypto.decompress_signature(compressed)
164 }
165
166 pub fn sign_hybrid_compressed(
167 hybrid_crypto: &HybridCrypto,
168 hybrid_keypair: &HybridKeyPair,
169 message: &[u8],
170 ) -> Result<CompressedHybridSignature> {
171 hybrid_crypto.sign_hybrid_compressed(hybrid_keypair, message)
172 }
173
174 pub fn verify_hybrid_compressed(
175 hybrid_crypto: &HybridCrypto,
176 hybrid_keypair: &HybridKeyPair,
177 message: &[u8],
178 compressed_signature: &CompressedHybridSignature,
179 ) -> Result<bool> {
180 hybrid_crypto.verify_hybrid_compressed(hybrid_keypair, message, compressed_signature)
181 }
182
183 pub fn compress_signature_with_metrics(
184 hybrid_crypto: &HybridCrypto,
185 signature: &HybridSignature,
186 ) -> Result<(CompressedHybridSignature, CompressionMetrics)> {
187 hybrid_crypto.compress_signature_with_metrics(signature)
188 }
189}
190
191#[cfg(test)]
192mod tests {
193 use super::*;
194
195 #[test]
196 fn test_unified_api_ecdsa_k256() {
197 let keypair = QuroxCrypto::generate_ecdsa_keypair(EcdsaCurve::K256).unwrap();
198 let message = b"test message";
199
200 let signature = QuroxCrypto::sign(&keypair.private_key, message).unwrap();
201 let is_valid = QuroxCrypto::verify(&keypair.public_key, message, &signature).unwrap();
202
203 assert!(is_valid);
204 }
205
206 #[test]
207 fn test_unified_api_ecdsa_p256() {
208 let keypair = QuroxCrypto::generate_ecdsa_keypair(EcdsaCurve::P256).unwrap();
209 let message = b"test message";
210
211 let signature = QuroxCrypto::sign(&keypair.private_key, message).unwrap();
212 let is_valid = QuroxCrypto::verify(&keypair.public_key, message, &signature).unwrap();
213
214 assert!(is_valid);
215 }
216
217 #[test]
218 fn test_unified_api_schnorr() {
219 let keypair = QuroxCrypto::generate_schnorr_keypair().unwrap();
220 let message = b"test message";
221
222 let signature = QuroxCrypto::sign(&keypair.private_key, message).unwrap();
223 let is_valid = QuroxCrypto::verify(&keypair.public_key, message, &signature).unwrap();
224
225 assert!(is_valid);
226 }
227
228 #[test]
229 fn test_unified_api_mldsa() {
230 let keypair = QuroxCrypto::generate_mldsa_keypair().unwrap();
231 let message = b"post-quantum test";
232
233 let signature = QuroxCrypto::sign(&keypair.private_key, message).unwrap();
234 let is_valid = QuroxCrypto::verify(&keypair.public_key, message, &signature).unwrap();
235
236 assert!(is_valid);
237 }
238
239 #[test]
240 fn test_unified_api_slh_dsa() {
241 let keypair = QuroxCrypto::generate_slh_dsa_keypair().unwrap();
242 let message = b"stateless hash test";
243
244 let signature = QuroxCrypto::sign(&keypair.private_key, message).unwrap();
245 let is_valid = QuroxCrypto::verify(&keypair.public_key, message, &signature).unwrap();
246
247 assert!(is_valid);
248 }
249
250 #[test]
251 fn test_unified_api_mlkem() {
252 let keypair = QuroxCrypto::generate_mlkem_keypair().unwrap();
253
254 let encryption_result = QuroxCrypto::encapsulate(&keypair.public_key).unwrap();
255 let decrypted_secret =
256 QuroxCrypto::decapsulate(&keypair.private_key, &encryption_result.ciphertext).unwrap();
257
258 assert_eq!(encryption_result.shared_secret.as_slice(), decrypted_secret.as_slice());
259 }
260
261 #[test]
262 fn test_hybrid_crypto_api() {
263 let hybrid_crypto = QuroxCrypto::create_hybrid_crypto_default();
264 let hybrid_keypair = QuroxCrypto::generate_hybrid_keypair(&hybrid_crypto).unwrap();
265 let message = b"hybrid crypto test";
266
267 let signature = QuroxCrypto::sign_hybrid(&hybrid_crypto, &hybrid_keypair, message).unwrap();
268 let is_valid =
269 QuroxCrypto::verify_hybrid(&hybrid_crypto, &hybrid_keypair, message, &signature)
270 .unwrap();
271
272 assert!(is_valid);
273 assert_eq!(signature.metadata.security_level, SecurityLevel::Hybrid);
274 }
275
276 #[test]
277 fn test_compression_api() {
278 let hybrid_crypto = QuroxCrypto::create_hybrid_crypto_default();
279 let hybrid_keypair = QuroxCrypto::generate_hybrid_keypair(&hybrid_crypto).unwrap();
280 let message = b"compression api test";
281
282 let compressed_signature =
283 QuroxCrypto::sign_hybrid_compressed(&hybrid_crypto, &hybrid_keypair, message).unwrap();
284 let is_valid = QuroxCrypto::verify_hybrid_compressed(
285 &hybrid_crypto,
286 &hybrid_keypair,
287 message,
288 &compressed_signature,
289 )
290 .unwrap();
291
292 assert!(is_valid);
293 }
294
295 #[test]
296 fn test_compression_engine_api() {
297 let compression_engine = QuroxCrypto::create_compression_engine_default();
298 let test_data = b"compression engine test data".repeat(10);
299
300 let compressed = compression_engine.compress_data(&test_data).unwrap();
301 let decompressed = compression_engine.decompress_data(&compressed).unwrap();
302
303 assert_eq!(test_data, decompressed);
304 }
305}