Skip to main content

qualia_core_db/specialized_libs/cryptographic_library/
signing.rs

1// Part of the cryptographic_library module (split from the former mod.rs monolith
2// per CLAUDE.md §11 — pure code motion, no behaviour change).
3use super::*;
4
5/// Signature engine for digital signatures
6pub struct SignatureEngine {
7    signing_algorithms: HashMap<KeyAlgorithm, SigningAlgorithm>,
8    verification_algorithms: HashMap<KeyAlgorithm, VerificationAlgorithm>,
9    pub(super) signature_storage: SignatureStorage,
10    pub(super) performance_optimizer: SignaturePerformanceOptimizer,
11}
12
13/// Signing algorithms
14#[derive(Debug, Clone)]
15pub struct SigningAlgorithm {
16    pub algorithm_id: String,
17    pub key_algorithm: KeyAlgorithm,
18    pub hash_function: String,
19    pub parameters: SigningParameters,
20}
21
22/// Signing parameters
23#[derive(Debug, Clone)]
24pub struct SigningParameters {
25    pub padding: Option<String>,
26    pub salt_length: Option<usize>,
27    pub deterministic: bool,
28    pub custom_params: HashMap<String, Vec<u8>>,
29}
30
31/// Verification algorithm configuration
32#[derive(Debug, Clone)]
33pub struct VerificationAlgorithmConfig {
34    pub algorithm_id: String,
35    pub key_algorithm: KeyAlgorithm,
36    pub hash_function: String,
37    pub parameters: VerificationParameters,
38}
39
40/// Verification parameters
41#[derive(Debug, Clone)]
42pub struct VerificationParameters {
43    pub strict_verification: bool,
44    pub allow_weak_hashes: bool,
45    pub custom_params: HashMap<String, Vec<u8>>,
46}
47
48/// Signature storage
49pub struct SignatureStorage {
50    signatures: HashMap<String, Signature>,
51    verification_records: HashMap<String, VerificationRecord>,
52    pub(super) audit_log: SignatureAuditLog,
53}
54
55/// Signature record
56#[derive(Debug, Clone)]
57pub struct SignatureRecord {
58    pub signature_id: String,
59    pub key_id: String,
60    pub algorithm: KeyAlgorithm,
61    pub data_hash: Vec<u8>,
62    pub signature: Vec<u8>,
63    pub timestamp: u64,
64    pub metadata: SignatureMetadata,
65}
66
67/// Signature metadata
68#[derive(Debug, Clone)]
69pub struct SignatureMetadata {
70    pub signer_id: String,
71    pub purpose: String,
72    pub context: Vec<String>,
73    pub validity_period: Option<(u64, u64)>,
74}
75
76/// Verification record
77#[derive(Debug, Clone)]
78pub struct VerificationRecord {
79    pub verification_id: String,
80    pub signature_id: String,
81    pub verifier_id: String,
82    pub result: VerificationResult,
83    pub timestamp: u64,
84}
85
86/// Verification result
87#[derive(Debug, Clone)]
88pub struct VerificationResult {
89    pub valid: bool,
90    pub error_message: Option<String>,
91    pub verification_time: u64,
92    pub confidence: f64,
93}
94
95/// Signature audit log
96pub struct SignatureAuditLog {
97    entries: Vec<SignatureAuditEntry>,
98    retention_policy: RetentionPolicy,
99}
100
101/// Signature audit entry
102#[derive(Debug, Clone)]
103pub struct SignatureAuditEntry {
104    pub entry_id: String,
105    pub timestamp: u64,
106    pub signature_id: String,
107    pub operation: SignatureOperation,
108    pub user_id: String,
109    pub ip_address: String,
110    pub success: bool,
111}
112
113/// Signature operations
114#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
115pub enum SignatureOperation {
116    Sign,
117    Verify,
118    Revoke,
119    Renew,
120}
121
122/// Signature performance optimizer
123pub struct SignaturePerformanceOptimizer {
124    optimization_strategies: Vec<SignatureOptimizationStrategy>,
125    performance_metrics: SignaturePerformanceMetrics,
126}
127
128/// Signature optimization strategies
129#[derive(Debug, Clone, PartialEq)]
130pub enum SignatureOptimizationStrategy {
131    BatchSigning,
132    Precomputation,
133    ParallelVerification,
134    Caching,
135    HardwareAcceleration,
136}
137
138/// Signature performance metrics
139#[derive(Debug, Clone)]
140pub struct SignaturePerformanceMetrics {
141    pub average_signing_time: f64,
142    pub average_verification_time: f64,
143    pub throughput: f64,
144    pub error_rate: f64,
145    pub cache_hit_rate: f64,
146}
147impl SignatureEngine {
148    pub fn new() -> Self {
149        Self {
150            signing_algorithms: HashMap::new(),
151            verification_algorithms: HashMap::new(),
152            signature_storage: SignatureStorage::new(),
153            performance_optimizer: SignaturePerformanceOptimizer::new(),
154        }
155    }
156
157    pub fn initialize(&mut self) -> Result<(), CryptographicError> {
158        self.signature_storage.initialize()?;
159        self.performance_optimizer.initialize()?;
160        Ok(())
161    }
162
163    /// Register a signing algorithm configuration.
164    pub fn add_signing_algorithm(&mut self, algorithm: SigningAlgorithm) {
165        self.signing_algorithms
166            .insert(algorithm.key_algorithm, algorithm);
167    }
168
169    /// Look up a signing algorithm by key algorithm.
170    pub fn get_signing_algorithm(&self, algorithm: &KeyAlgorithm) -> Option<&SigningAlgorithm> {
171        self.signing_algorithms.get(algorithm)
172    }
173
174    /// Iterate over all registered signing algorithms.
175    pub fn list_signing_algorithms(&self) -> impl Iterator<Item = &SigningAlgorithm> {
176        self.signing_algorithms.values()
177    }
178
179    /// Register a verification algorithm configuration.
180    pub fn add_verification_algorithm(
181        &mut self,
182        key_algorithm: KeyAlgorithm,
183        algorithm: VerificationAlgorithm,
184    ) {
185        self.verification_algorithms
186            .insert(key_algorithm, algorithm);
187    }
188
189    /// Look up a verification algorithm by key algorithm.
190    pub fn get_verification_algorithm(
191        &self,
192        algorithm: &KeyAlgorithm,
193    ) -> Option<&VerificationAlgorithm> {
194        self.verification_algorithms.get(algorithm)
195    }
196
197    /// Iterate over all registered verification algorithms.
198    pub fn list_verification_algorithms(&self) -> impl Iterator<Item = &VerificationAlgorithm> {
199        self.verification_algorithms.values()
200    }
201
202    /// Deterministic ML-DSA context used for fiduciary sign/verify in this library.
203    /// Sign and verify must use the same context, so it is fixed here.
204    fn fiduciary_context() -> CryptoContext {
205        CryptoContext {
206            domain: "qualia.fiduciary".to_string(),
207            purpose: "sign".to_string(),
208            timestamp: 0,
209            nonce: [0u8; 32],
210        }
211    }
212
213    pub fn sign_data(
214        &mut self,
215        private_key: &Key,
216        data: &[u8],
217    ) -> Result<Signature, CryptographicError> {
218        let start_time = std::time::Instant::now();
219
220        let signature_data = match private_key.key_algorithm {
221            KeyAlgorithm::MLDSA => {
222                // Real ML-DSA signs the message directly (it hashes internally); no
223                // SHA-256 prehash, and the key material is the full FIPS-204 secret key.
224                let ctx = Self::fiduciary_context();
225                let sig = MlDsaSigner::sign_with_secret(&private_key.key_data, data, &ctx)
226                    .map_err(|e| {
227                        CryptographicError::SignatureError(format!("ML-DSA sign failed: {e}"))
228                    })?;
229                sig.sig_bytes
230            }
231            KeyAlgorithm::SPHINCS => {
232                use fips205::slh_dsa_sha2_256s;
233                use fips205::traits::{SerDes, Signer};
234                let sk_arr: [u8; slh_dsa_sha2_256s::SK_LEN] =
235                    private_key.key_data.as_slice().try_into().map_err(|_| {
236                        CryptographicError::InvalidKey(format!(
237                            "SPHINCS secret key must be {} bytes",
238                            slh_dsa_sha2_256s::SK_LEN
239                        ))
240                    })?;
241                let sk = slh_dsa_sha2_256s::PrivateKey::try_from_bytes(&sk_arr)
242                    .map_err(|e| CryptographicError::SignatureError(e.to_string()))?;
243                let sig = sk
244                    .try_sign(data, b"", true)
245                    .map_err(|e| CryptographicError::SignatureError(e.to_string()))?;
246                sig.to_vec()
247            }
248            KeyAlgorithm::ECDSA => {
249                #[cfg(feature = "interop-crypto")]
250                {
251                    use crate::fiduciary_crypto::InteropEcdsaSigner;
252                    let signer = InteropEcdsaSigner::from_secret_key(&private_key.key_data)
253                        .map_err(|e| CryptographicError::SignatureError(e.to_string()))?;
254                    let sig = signer
255                        .sign(data)
256                        .map_err(|e| CryptographicError::SignatureError(e.to_string()))?;
257                    sig.sig_bytes
258                }
259                #[cfg(not(feature = "interop-crypto"))]
260                {
261                    return Err(CryptographicError::UnsupportedAlgorithm(
262                        "ECDSA requires interop-crypto feature".to_string(),
263                    ));
264                }
265            }
266            KeyAlgorithm::RSA => {
267                #[cfg(feature = "interop-crypto")]
268                {
269                    use rsa::pkcs1v15::SigningKey;
270                    use rsa::sha2::Sha256;
271                    use rsa::signature::{SignatureEncoding, Signer};
272                    use rsa::{pkcs8::DecodePrivateKey, RsaPrivateKey};
273                    let priv_key = RsaPrivateKey::from_pkcs8_der(&private_key.key_data)
274                        .map_err(|e| CryptographicError::SignatureError(e.to_string()))?;
275                    let signing_key = SigningKey::<Sha256>::new(priv_key);
276                    signing_key.sign(data).to_bytes().to_vec()
277                }
278                #[cfg(not(feature = "interop-crypto"))]
279                {
280                    return Err(CryptographicError::UnsupportedAlgorithm(
281                        "RSA requires interop-crypto feature".to_string(),
282                    ));
283                }
284            }
285            _ => {
286                // Ed25519 over a SHA-256 digest of the data.
287                let hash = self.compute_data_hash(data)?;
288                self.sign_hash(&private_key, &hash)?
289            }
290        };
291
292        let signature = Signature {
293            signature_id: format!(
294                "sig_{}",
295                std::time::SystemTime::now()
296                    .duration_since(std::time::UNIX_EPOCH)
297                    .unwrap()
298                    .as_secs()
299            ),
300            key_id: private_key.key_id.clone(),
301            algorithm: private_key.key_algorithm.clone(),
302            data: data.to_vec(),
303            signature: signature_data,
304            timestamp: start_time.elapsed().as_millis() as u64,
305        };
306
307        // Store signature
308        self.signature_storage.store_signature(signature.clone())?;
309
310        // Audit log the signing operation
311        self.signature_storage.audit_log.log_entry(
312            &signature.signature_id,
313            SignatureOperation::Sign,
314            "system",
315            true,
316        );
317
318        // Record performance metrics
319        self.performance_optimizer
320            .record_signing_time(start_time.elapsed().as_millis() as f64);
321
322        Ok(signature)
323    }
324
325    pub fn verify_signature(
326        &mut self,
327        public_key: &Key,
328        signature: &Signature,
329        data: &[u8],
330    ) -> Result<bool, CryptographicError> {
331        let start_time = std::time::Instant::now();
332
333        let is_valid = match public_key.key_algorithm {
334            KeyAlgorithm::MLDSA => {
335                let ctx = Self::fiduciary_context();
336                let sig = MlDsaSignature {
337                    sig_bytes: signature.signature.clone(),
338                };
339                MlDsaSigner::verify_with_public(&public_key.key_data, data, &sig, &ctx).map_err(
340                    |e| CryptographicError::SignatureError(format!("ML-DSA verify failed: {e}")),
341                )?
342            }
343            KeyAlgorithm::SPHINCS => {
344                use fips205::slh_dsa_sha2_256s;
345                use fips205::traits::{SerDes, Verifier};
346                let pk_arr: [u8; slh_dsa_sha2_256s::PK_LEN] =
347                    public_key.key_data.as_slice().try_into().map_err(|_| {
348                        CryptographicError::InvalidKey(format!(
349                            "SPHINCS public key must be {} bytes",
350                            slh_dsa_sha2_256s::PK_LEN
351                        ))
352                    })?;
353                let pk = slh_dsa_sha2_256s::PublicKey::try_from_bytes(&pk_arr)
354                    .map_err(|e| CryptographicError::SignatureError(e.to_string()))?;
355                if signature.signature.len() != slh_dsa_sha2_256s::SIG_LEN {
356                    return Ok(false);
357                }
358                let mut sig_arr = [0u8; slh_dsa_sha2_256s::SIG_LEN];
359                sig_arr.copy_from_slice(&signature.signature);
360                pk.verify(data, &sig_arr, b"")
361            }
362            KeyAlgorithm::ECDSA => {
363                #[cfg(feature = "interop-crypto")]
364                {
365                    use crate::fiduciary_crypto::{InteropEcdsaSignature, InteropEcdsaSigner};
366                    let signer = InteropEcdsaSigner::from_public_key(&public_key.key_data)
367                        .map_err(|e| CryptographicError::SignatureError(e.to_string()))?;
368                    let sig = InteropEcdsaSignature {
369                        sig_bytes: signature.signature.clone(),
370                    };
371                    signer
372                        .verify(data, &sig)
373                        .map_err(|e| CryptographicError::SignatureError(e.to_string()))?
374                }
375                #[cfg(not(feature = "interop-crypto"))]
376                {
377                    return Err(CryptographicError::UnsupportedAlgorithm(
378                        "ECDSA requires interop-crypto feature".to_string(),
379                    ));
380                }
381            }
382            KeyAlgorithm::RSA => {
383                #[cfg(feature = "interop-crypto")]
384                {
385                    use rsa::pkcs1v15::{Signature as RsaSignature, VerifyingKey};
386                    use rsa::sha2::Sha256;
387                    use rsa::signature::Verifier;
388                    use rsa::{pkcs8::DecodePublicKey, RsaPublicKey};
389                    let pub_key = RsaPublicKey::from_public_key_der(&public_key.key_data)
390                        .map_err(|e| CryptographicError::SignatureError(e.to_string()))?;
391                    let verifying_key = VerifyingKey::<Sha256>::new(pub_key);
392                    let sig = RsaSignature::try_from(signature.signature.as_slice())
393                        .map_err(|e| CryptographicError::SignatureError(e.to_string()))?;
394                    verifying_key.verify(data, &sig).is_ok()
395                }
396                #[cfg(not(feature = "interop-crypto"))]
397                {
398                    return Err(CryptographicError::UnsupportedAlgorithm(
399                        "RSA requires interop-crypto feature".to_string(),
400                    ));
401                }
402            }
403            _ => {
404                let hash = self.compute_data_hash(data)?;
405                self.verify_hash_signature(&public_key, &signature.signature, &hash)?
406            }
407        };
408
409        // Store verification record
410        let verification_record = VerificationRecord {
411            verification_id: format!(
412                "verif_{}",
413                std::time::SystemTime::now()
414                    .duration_since(std::time::UNIX_EPOCH)
415                    .unwrap()
416                    .as_secs()
417            ),
418            signature_id: signature.signature_id.clone(),
419            verifier_id: "system".to_string(),
420            result: VerificationResult {
421                valid: is_valid,
422                error_message: None,
423                verification_time: start_time.elapsed().as_millis() as u64,
424                confidence: 1.0,
425            },
426            timestamp: start_time.elapsed().as_millis() as u64,
427        };
428
429        self.signature_storage
430            .store_verification_record(verification_record)?;
431
432        // Audit log the verification operation
433        self.signature_storage.audit_log.log_entry(
434            &signature.signature_id,
435            SignatureOperation::Verify,
436            "system",
437            is_valid,
438        );
439
440        // Record performance metrics
441        self.performance_optimizer
442            .record_verification_time(start_time.elapsed().as_millis() as f64);
443        if !is_valid {
444            self.performance_optimizer.record_error();
445        }
446
447        Ok(is_valid)
448    }
449
450    fn compute_data_hash(&self, data: &[u8]) -> Result<Vec<u8>, CryptographicError> {
451        // Compute SHA-256 hash
452        use sha2::{Digest, Sha256};
453        let mut hasher = Sha256::new();
454        hasher.update(data);
455        Ok(hasher.finalize().to_vec())
456    }
457
458    fn sign_hash(&self, private_key: &Key, hash: &[u8]) -> Result<Vec<u8>, CryptographicError> {
459        use ed25519_dalek::{Signer, SigningKey};
460        if private_key.key_data.len() < 32 {
461            return Err(CryptographicError::InvalidKey(
462                "Private key too short for signing".to_string(),
463            ));
464        }
465        let mut seed = [0u8; 32];
466        seed.copy_from_slice(&private_key.key_data[..32]);
467        let signing_key = SigningKey::from_bytes(&seed);
468        let sig = signing_key.sign(hash);
469        Ok(sig.to_bytes().to_vec())
470    }
471
472    fn verify_hash_signature(
473        &self,
474        public_key: &Key,
475        signature: &[u8],
476        hash: &[u8],
477    ) -> Result<bool, CryptographicError> {
478        use ed25519_dalek::{Signature, Verifier, VerifyingKey};
479        if public_key.key_data.len() < 32 {
480            return Err(CryptographicError::InvalidKey(
481                "Public key too short for verification".to_string(),
482            ));
483        }
484        let mut key_bytes = [0u8; 32];
485        key_bytes.copy_from_slice(&public_key.key_data[..32]);
486        let verifying_key = VerifyingKey::from_bytes(&key_bytes)
487            .map_err(|e| CryptographicError::InvalidKey(e.to_string()))?;
488        if signature.len() != 64 {
489            return Ok(false);
490        }
491        let mut sig_bytes = [0u8; 64];
492        sig_bytes.copy_from_slice(signature);
493        let sig = Signature::from_bytes(&sig_bytes);
494        Ok(verifying_key.verify(hash, &sig).is_ok())
495    }
496}
497
498impl SignatureStorage {
499    pub fn new() -> Self {
500        Self {
501            signatures: HashMap::new(),
502            verification_records: HashMap::new(),
503            audit_log: SignatureAuditLog::new(),
504        }
505    }
506
507    pub fn initialize(&mut self) -> Result<(), CryptographicError> {
508        Ok(())
509    }
510
511    pub fn store_signature(&mut self, signature: Signature) -> Result<(), CryptographicError> {
512        self.signatures
513            .insert(signature.signature_id.clone(), signature);
514        Ok(())
515    }
516
517    pub fn store_verification_record(
518        &mut self,
519        record: VerificationRecord,
520    ) -> Result<(), CryptographicError> {
521        self.verification_records
522            .insert(record.verification_id.clone(), record);
523        Ok(())
524    }
525}
526
527impl SignatureAuditLog {
528    pub fn new() -> Self {
529        Self {
530            entries: Vec::new(),
531            retention_policy: RetentionPolicy {
532                retention_days: 365,
533                auto_delete: true,
534                archive_before_delete: true,
535            },
536        }
537    }
538
539    /// Record a signature operation (sign, verify, revoke, renew).
540    pub fn log_entry(
541        &mut self,
542        signature_id: &str,
543        operation: SignatureOperation,
544        user_id: &str,
545        success: bool,
546    ) {
547        let timestamp = std::time::SystemTime::now()
548            .duration_since(std::time::UNIX_EPOCH)
549            .unwrap_or_default()
550            .as_secs();
551        let entry = SignatureAuditEntry {
552            entry_id: format!("sig_{}_{}", timestamp, self.entries.len()),
553            timestamp,
554            signature_id: signature_id.to_string(),
555            operation,
556            user_id: user_id.to_string(),
557            ip_address: String::new(),
558            success,
559        };
560        self.entries.push(entry);
561        let cutoff =
562            timestamp.saturating_sub((self.retention_policy.retention_days as u64) * 86400);
563        self.entries.retain(|e| e.timestamp >= cutoff);
564    }
565
566    /// Number of logged entries.
567    pub fn entry_count(&self) -> usize {
568        self.entries.len()
569    }
570
571    /// Iterate over entries.
572    pub fn entries(&self) -> &[SignatureAuditEntry] {
573        &self.entries
574    }
575}
576
577impl SignaturePerformanceOptimizer {
578    pub fn new() -> Self {
579        Self {
580            optimization_strategies: vec![
581                SignatureOptimizationStrategy::BatchSigning,
582                SignatureOptimizationStrategy::Caching,
583            ],
584            performance_metrics: SignaturePerformanceMetrics {
585                average_signing_time: 0.0,
586                average_verification_time: 0.0,
587                throughput: 0.0,
588                error_rate: 0.0,
589                cache_hit_rate: 0.0,
590            },
591        }
592    }
593
594    pub fn initialize(&mut self) -> Result<(), CryptographicError> {
595        Ok(())
596    }
597
598    /// Get the configured optimization strategies.
599    pub fn optimization_strategies(&self) -> &[SignatureOptimizationStrategy] {
600        &self.optimization_strategies
601    }
602
603    /// Add an optimization strategy if not already present.
604    pub fn add_optimization_strategy(&mut self, strategy: SignatureOptimizationStrategy) {
605        if !self.optimization_strategies.contains(&strategy) {
606            self.optimization_strategies.push(strategy);
607        }
608    }
609
610    /// Record a signing operation duration (milliseconds) and update running averages.
611    pub fn record_signing_time(&mut self, duration_ms: f64) {
612        let m = &mut self.performance_metrics;
613        if m.average_signing_time == 0.0 {
614            m.average_signing_time = duration_ms;
615        } else {
616            // Exponential moving average for lightweight online tracking
617            m.average_signing_time = 0.9 * m.average_signing_time + 0.1 * duration_ms;
618        }
619        if duration_ms > 0.0 {
620            m.throughput = 1000.0 / m.average_signing_time;
621        }
622    }
623
624    /// Record a verification operation duration (milliseconds).
625    pub fn record_verification_time(&mut self, duration_ms: f64) {
626        let m = &mut self.performance_metrics;
627        if m.average_verification_time == 0.0 {
628            m.average_verification_time = duration_ms;
629        } else {
630            m.average_verification_time = 0.9 * m.average_verification_time + 0.1 * duration_ms;
631        }
632    }
633
634    /// Record an error (failed sign/verify).
635    pub fn record_error(&mut self) {
636        let m = &mut self.performance_metrics;
637        // Simple error rate approximation — incrementally adjusted
638        m.error_rate = 0.95 * m.error_rate + 0.05;
639    }
640
641    /// Get a snapshot of the current performance metrics.
642    pub fn metrics(&self) -> &SignaturePerformanceMetrics {
643        &self.performance_metrics
644    }
645}
646
647impl SignaturePerformanceMetrics {
648    pub fn new() -> Self {
649        Self {
650            average_signing_time: 0.0,
651            average_verification_time: 0.0,
652            throughput: 0.0,
653            error_rate: 0.0,
654            cache_hit_rate: 0.0,
655        }
656    }
657}