Skip to main content

runar_keys/
node.rs

1//! Node Key Manager - Certificate Request and Management
2//!
3//! This module implements the node-side key management system that generates
4//! certificate signing requests (CSRs) and manages received certificates.
5
6use crate::certificate::{CertificateRequest, CertificateValidator, EcdsaKeyPair, X509Certificate};
7use crate::error::{KeyError, Result};
8use crate::mobile::{EnvelopeEncryptedData, NetworkKeyMessage, NodeCertificateMessage, SetupToken};
9use crate::{log_debug, log_info, log_warn};
10// use p256::ecdsa::SigningKey; // no longer needed here
11use p256::elliptic_curve::sec1::ToEncodedPoint;
12use p256::SecretKey as P256SecretKey;
13use pkcs8::{DecodePrivateKey, EncodePrivateKey};
14use rand::RngCore;
15use runar_common::compact_ids::compact_id;
16use runar_common::logging::Logger;
17use rustls_pki_types::{CertificateDer, PrivateKeyDer};
18use serde::{Deserialize, Serialize};
19use std::collections::HashMap;
20use std::sync::Arc;
21
22/// QUIC certificate configuration for transport layer
23#[derive(Debug)]
24pub struct QuicCertificateConfig {
25    /// Certificate chain (node certificate + CA certificate)
26    pub certificate_chain: Vec<CertificateDer<'static>>,
27    /// Private key for the node certificate
28    pub private_key: PrivateKeyDer<'static>,
29    /// Certificate validator for peer certificates
30    pub certificate_validator: CertificateValidator,
31}
32
33/// Node certificate status
34#[derive(Debug, Clone, PartialEq)]
35pub enum CertificateStatus {
36    /// No certificate installed
37    None,
38    /// Certificate pending (CSR sent, waiting for response)
39    Pending,
40    /// Certificate installed and valid
41    Valid,
42    /// Certificate expired or invalid
43    Invalid,
44}
45
46/// Node Key Manager for certificate requests and management
47pub struct NodeKeyManager {
48    /// Node's identity key pair (always present)
49    node_key_pair: EcdsaKeyPair,
50    /// Node's certificate (if issued by CA)
51    node_certificate: Option<X509Certificate>,
52    /// CA certificate for validation
53    ca_certificate: Option<X509Certificate>,
54    /// Certificate validator
55    certificate_validator: Option<CertificateValidator>,
56    /// Network agreement secrets indexed by network id
57    network_agreements: HashMap<String, P256SecretKey>,
58
59    /// Network public keys indexed by network id
60    network_public_keys: HashMap<String, Vec<u8>>,
61
62    /// Known user profile public keys (id -> public key bytes)
63    profile_public_keys: HashMap<String, Vec<u8>>,
64    /// Symmetric keys indexed by key name for services
65    symmetric_keys: HashMap<String, Vec<u8>>,
66    /// Node storage key for local file encryption (always present)
67    storage_key: Vec<u8>,
68    /// Node agreement private key (used for ECIES)
69    node_agreement_secret: P256SecretKey,
70    /// Certificate status
71    certificate_status: CertificateStatus,
72    /// Logger instance
73    logger: Arc<Logger>,
74}
75
76impl NodeKeyManager {
77    /// Create a new Node Key Manager with fresh keys
78    pub fn new(logger: Arc<Logger>) -> Result<Self> {
79        // Generate node identity key pair
80        let node_key_pair = EcdsaKeyPair::new()?;
81
82        // Derive node storage key (HKDF-SHA-256 from node identity master)
83        let storage_key = {
84            use hkdf::Hkdf;
85            use sha2::Sha256;
86            let ikm = node_key_pair.signing_key().to_bytes();
87            let hk = Hkdf::<Sha256>::new(Some(b"RunarKeyDerivationSalt/v1"), ikm.as_slice());
88            let mut key = [0u8; 32];
89            hk.expand(b"runar-v1:node-identity:storage", &mut key)
90                .map_err(|e| KeyError::KeyDerivationError(format!("HKDF expansion failed: {e}")))?;
91            key.to_vec()
92        };
93
94        // Derive node agreement key from node master signing key
95        let node_agreement_secret = crate::derivation::derive_agreement_from_master(
96            &node_key_pair.signing_key().to_bytes(),
97            b"runar-v1:node-identity:agreement",
98        )?;
99
100        let node_public_key = node_key_pair.public_key_bytes();
101        let node_public_key_str = compact_id(&node_public_key);
102        log_info!(
103            logger,
104            "Node Key Manager created with identity: {node_public_key_str}"
105        );
106        log_debug!(logger, "Node storage key generated for local encryption");
107
108        Ok(Self {
109            node_key_pair,
110            node_certificate: None,
111            ca_certificate: None,
112            certificate_validator: None,
113            network_agreements: HashMap::new(),
114            network_public_keys: HashMap::new(),
115            symmetric_keys: HashMap::new(),
116            storage_key,
117            node_agreement_secret,
118            certificate_status: CertificateStatus::None,
119            logger,
120            profile_public_keys: HashMap::new(),
121        })
122    }
123
124    /// Get the node public key (node ID) - keys are always available
125    pub fn get_node_public_key(&self) -> Vec<u8> {
126        self.node_key_pair.public_key_bytes()
127    }
128
129    /// Get the node ID (compact Base58 encoding of public key)
130    pub fn get_node_id(&self) -> String {
131        compact_id(&self.node_key_pair.public_key_bytes())
132    }
133
134    // Removed random storage key generator; storage keys are derived via HKDF from the node master key
135
136    /// Get the node storage key for local encryption
137    pub fn get_storage_key(&self) -> &[u8] {
138        &self.storage_key
139    }
140
141    /// Ensure a symmetric key exists with the given name, creating it if it doesn't exist
142    pub fn ensure_symmetric_key(&mut self, key_name: &str) -> Result<Vec<u8>> {
143        if let Some(key) = self.symmetric_keys.get(key_name) {
144            return Ok(key.clone());
145        }
146
147        // Generate a new 32-byte symmetric key
148        let mut key = [0u8; 32];
149        rand::thread_rng().fill_bytes(&mut key);
150        let key_vec = key.to_vec();
151
152        // Store the key for future use
153        self.symmetric_keys
154            .insert(key_name.to_string(), key_vec.clone());
155
156        log_debug!(self.logger, "Generated new symmetric key: {key_name}");
157        Ok(key_vec)
158    }
159
160    /// Encrypt local data using the node storage key
161    pub fn encrypt_local_data(&self, data: &[u8]) -> Result<Vec<u8>> {
162        let storage_key = self.get_storage_key();
163
164        // Use AES-256-GCM for secure local data encryption
165        self.encrypt_with_symmetric_key(data, storage_key)
166    }
167
168    /// Decrypt local data using the node storage key
169    pub fn decrypt_local_data(&self, encrypted_data: &[u8]) -> Result<Vec<u8>> {
170        let storage_key = self.get_storage_key();
171
172        // Use AES-256-GCM for secure local data decryption
173        self.decrypt_with_symmetric_key(encrypted_data, storage_key)
174    }
175
176    /// Decrypt envelope-encrypted data using network key
177    pub fn decrypt_envelope_data(
178        &self,
179        envelope_data: &crate::mobile::EnvelopeEncryptedData,
180    ) -> Result<Vec<u8>> {
181        let network_id = envelope_data
182            .network_id
183            .as_ref()
184            .ok_or_else(|| KeyError::DecryptionError("Envelope missing network_id".to_string()))?;
185
186        let network_key_pair = self.network_agreements.get(network_id).ok_or_else(|| {
187            KeyError::KeyNotFound(format!(
188                "Network key pair not found for network: {network_id}"
189            ))
190        })?;
191
192        // Ensure the encrypted envelope key is present
193        let encrypted_envelope_key = &envelope_data.network_encrypted_key;
194        if encrypted_envelope_key.is_empty() {
195            return Err(KeyError::DecryptionError(
196                "Envelope missing network_encrypted_key".to_string(),
197            ));
198        }
199
200        let envelope_key =
201            self.decrypt_key_with_agreement(encrypted_envelope_key, network_key_pair)?;
202        self.decrypt_with_symmetric_key(&envelope_data.encrypted_data, &envelope_key)
203    }
204
205    /// Create an envelope-encrypted data structure for sharing
206    pub fn create_envelope_for_network(
207        &self,
208        data: &[u8],
209        network_id: Option<&str>,
210    ) -> Result<crate::mobile::EnvelopeEncryptedData> {
211        let network_id = network_id
212            .ok_or_else(|| KeyError::DecryptionError("Missing network_id".to_string()))?;
213
214        let network_public_key_bytes = self.get_network_public_key(network_id)?;
215
216        // Generate ephemeral envelope key
217        let envelope_key = self.generate_envelope_key()?;
218
219        // Encrypt data with envelope key
220        let encrypted_data = self.encrypt_with_symmetric_key(data, &envelope_key)?;
221
222        // Encrypt envelope key with network key
223        let encrypted_envelope_key =
224            self.encrypt_key_with_ecdsa(&envelope_key, &network_public_key_bytes)?;
225
226        Ok(crate::mobile::EnvelopeEncryptedData {
227            encrypted_data,
228            network_id: Some(network_id.to_string()),
229            network_encrypted_key: encrypted_envelope_key,
230            profile_encrypted_keys: HashMap::new(),
231        })
232    }
233
234    /// Generate an ephemeral envelope key
235    fn generate_envelope_key(&self) -> Result<Vec<u8>> {
236        use rand::RngCore;
237        let mut envelope_key = [0u8; 32];
238        rand::thread_rng().fill_bytes(&mut envelope_key);
239        log_debug!(self.logger, "Ephemeral envelope key generated");
240        Ok(envelope_key.to_vec())
241    }
242
243    // Helper methods for cryptographic operations using AES-256-GCM
244    fn encrypt_with_symmetric_key(&self, data: &[u8], key: &[u8]) -> Result<Vec<u8>> {
245        use aes_gcm::{aead::Aead, Aes256Gcm, KeyInit, Nonce};
246        use rand::{thread_rng, RngCore};
247
248        if key.len() != 32 {
249            return Err(KeyError::SymmetricCipherError(
250                "Key must be 32 bytes for AES-256".to_string(),
251            ));
252        }
253
254        let cipher = Aes256Gcm::new_from_slice(key)
255            .map_err(|e| KeyError::SymmetricCipherError(format!("Failed to create cipher: {e}")))?;
256        let mut nonce = [0u8; 12];
257        thread_rng().fill_bytes(&mut nonce);
258
259        let ciphertext = cipher
260            .encrypt(Nonce::from_slice(&nonce), data)
261            .map_err(|e| KeyError::EncryptionError(format!("AES-GCM encryption failed: {e}")))?;
262
263        // Prepend nonce to ciphertext
264        let mut result = nonce.to_vec();
265        result.extend_from_slice(&ciphertext);
266        Ok(result)
267    }
268
269    fn decrypt_with_symmetric_key(&self, encrypted_data: &[u8], key: &[u8]) -> Result<Vec<u8>> {
270        use aes_gcm::{aead::Aead, Aes256Gcm, KeyInit, Nonce};
271
272        if key.len() != 32 {
273            return Err(KeyError::SymmetricCipherError(
274                "Key must be 32 bytes for AES-256".to_string(),
275            ));
276        }
277
278        if encrypted_data.len() < 12 {
279            return Err(KeyError::DecryptionError(
280                "Encrypted data too short (missing nonce)".to_string(),
281            ));
282        }
283
284        let cipher = Aes256Gcm::new_from_slice(key)
285            .map_err(|e| KeyError::SymmetricCipherError(format!("Failed to create cipher: {e}")))?;
286        let nonce = &encrypted_data[..12];
287        let ciphertext = &encrypted_data[12..];
288
289        cipher
290            .decrypt(Nonce::from_slice(nonce), ciphertext)
291            .map_err(|e| KeyError::DecryptionError(format!("AES-GCM decryption failed: {e}")))
292    }
293
294    /// Internal ECIES encryption using a recipient's public key
295    fn encrypt_key_with_ecdsa(
296        &self,
297        data: &[u8],
298        recipient_public_key_bytes: &[u8],
299    ) -> Result<Vec<u8>> {
300        use hkdf::Hkdf;
301        use p256::ecdh::EphemeralSecret;
302        use p256::elliptic_curve::sec1::ToEncodedPoint;
303        use p256::PublicKey;
304        use rand::thread_rng;
305        use sha2::Sha256;
306
307        // Generate ephemeral key pair for ECDH
308        let ephemeral_secret = EphemeralSecret::random(&mut thread_rng());
309        let ephemeral_public = ephemeral_secret.public_key();
310
311        // Convert recipient's public key bytes to PublicKey
312        let recipient_public_key =
313            PublicKey::from_sec1_bytes(recipient_public_key_bytes).map_err(|e| {
314                KeyError::InvalidKeyFormat(format!("Failed to parse recipient public key: {e}"))
315            })?;
316
317        // Perform ECDH key exchange
318        let shared_secret = ephemeral_secret.diffie_hellman(&recipient_public_key);
319        let shared_secret_bytes = shared_secret.raw_secret_bytes();
320
321        // Derive encryption key using HKDF-SHA-256
322        let hk = Hkdf::<Sha256>::new(None, shared_secret_bytes.as_slice());
323        let mut encryption_key = [0u8; 32];
324        hk.expand(b"runar-v1:ecies:envelope-key", &mut encryption_key)
325            .map_err(|e| KeyError::KeyDerivationError(format!("HKDF expansion failed: {e}")))?;
326
327        // Encrypt the data using AES-GCM
328        let encrypted_data = self.encrypt_with_symmetric_key(data, &encryption_key)?;
329
330        // Return ephemeral public key (97 bytes uncompressed) + encrypted data
331        let ephemeral_public_bytes = ephemeral_public.to_encoded_point(false);
332        let mut result = ephemeral_public_bytes.as_bytes().to_vec();
333        result.extend_from_slice(&encrypted_data);
334        Ok(result)
335    }
336
337    /// Internal ECIES decryption using our private key
338    fn decrypt_key_with_ecdsa(
339        &self,
340        encrypted_data: &[u8],
341        _key_pair: &EcdsaKeyPair,
342    ) -> Result<Vec<u8>> {
343        use hkdf::Hkdf;
344        use p256::ecdh::diffie_hellman;
345        use p256::PublicKey;
346        // use p256::SecretKey;
347        use sha2::Sha256;
348
349        // Extract ephemeral public key (65 bytes uncompressed) and encrypted data
350        if encrypted_data.len() < 65 {
351            return Err(KeyError::DecryptionError(
352                "Encrypted data too short for ECIES".to_string(),
353            ));
354        }
355
356        let ephemeral_public_bytes = &encrypted_data[..65];
357        let encrypted_payload = &encrypted_data[65..];
358
359        // Reconstruct ephemeral public key
360        let ephemeral_public = PublicKey::from_sec1_bytes(ephemeral_public_bytes).map_err(|e| {
361            KeyError::DecryptionError(format!("Failed to parse ephemeral public key: {e}"))
362        })?;
363
364        // Use node's agreement secret for ECDH
365        let shared_secret = diffie_hellman(
366            self.node_agreement_secret.to_nonzero_scalar(),
367            ephemeral_public.as_affine(),
368        );
369        let shared_secret_bytes = shared_secret.raw_secret_bytes();
370
371        // Derive encryption key using HKDF-SHA-256
372        let hk = Hkdf::<Sha256>::new(None, shared_secret_bytes);
373        let mut encryption_key = [0u8; 32];
374        hk.expand(b"runar-v1:ecies:envelope-key", &mut encryption_key)
375            .map_err(|e| KeyError::KeyDerivationError(format!("HKDF expansion failed: {e}")))?;
376
377        // Decrypt the data using AES-GCM
378        self.decrypt_with_symmetric_key(encrypted_payload, &encryption_key)
379    }
380
381    /// Internal ECIES decryption using an agreement private key
382    fn decrypt_key_with_agreement(
383        &self,
384        encrypted_data: &[u8],
385        agreement_secret: &P256SecretKey,
386    ) -> Result<Vec<u8>> {
387        use hkdf::Hkdf;
388        use p256::ecdh::diffie_hellman;
389        use p256::PublicKey;
390        use sha2::Sha256;
391
392        if encrypted_data.len() < 65 {
393            return Err(KeyError::DecryptionError(
394                "Encrypted data too short for ECIES".to_string(),
395            ));
396        }
397
398        let ephemeral_public_bytes = &encrypted_data[..65];
399        let encrypted_payload = &encrypted_data[65..];
400
401        let ephemeral_public = PublicKey::from_sec1_bytes(ephemeral_public_bytes).map_err(|e| {
402            KeyError::DecryptionError(format!("Failed to parse ephemeral public key: {e}"))
403        })?;
404
405        let shared_secret = diffie_hellman(
406            agreement_secret.to_nonzero_scalar(),
407            ephemeral_public.as_affine(),
408        );
409        let shared_secret_bytes = shared_secret.raw_secret_bytes();
410
411        let hk = Hkdf::<Sha256>::new(None, shared_secret_bytes);
412        let mut encryption_key = [0u8; 32];
413        hk.expand(b"runar-v1:ecies:envelope-key", &mut encryption_key)
414            .map_err(|e| KeyError::KeyDerivationError(format!("HKDF expansion failed: {e}")))?;
415
416        self.decrypt_with_symmetric_key(encrypted_payload, &encryption_key)
417    }
418
419    /// Generate a certificate signing request (CSR) for this node
420    pub fn generate_csr(&mut self) -> Result<SetupToken> {
421        let node_public_key = self.get_node_public_key();
422        let node_id = self.get_node_id();
423
424        // Convert to DNS-safe format for certificate generation
425        let dns_safe_node_id = self.dns_safe_node_id(&node_id);
426        let subject = format!("CN={dns_safe_node_id},O=Runar Node,C=US");
427
428        let csr_der = CertificateRequest::create(&self.node_key_pair, &subject)?;
429
430        self.certificate_status = CertificateStatus::Pending;
431
432        // Derive agreement from node master and include public part in token
433        let agreement = crate::derivation::derive_agreement_from_master(
434            &self.node_key_pair.signing_key().to_bytes(),
435            b"runar-v1:node-identity:agreement",
436        )?;
437        Ok(SetupToken {
438            node_public_key,
439            node_agreement_public_key: agreement
440                .public_key()
441                .to_encoded_point(false)
442                .as_bytes()
443                .to_vec(),
444            csr_der,
445            node_id,
446        })
447    }
448
449    /// Convert a compact ID to a DNS-safe format by replacing invalid characters
450    pub fn dns_safe_node_id(&self, node_id: &str) -> String {
451        node_id
452            .chars()
453            .map(|c| match c {
454                '-' => 'x',                    // Replace hyphen with 'x'
455                '_' => 'y',                    // Replace underscore with 'y'
456                c if c.is_alphanumeric() => c, // Keep alphanumeric
457                _ => 'z',                      // Replace any other invalid chars with 'z'
458            })
459            .collect()
460    }
461
462    /// Get the node key pair for certificate creation
463    pub fn get_node_key_pair(&self) -> &EcdsaKeyPair {
464        &self.node_key_pair
465    }
466
467    /// Install certificate received from mobile CA
468    pub fn install_certificate(&mut self, cert_message: NodeCertificateMessage) -> Result<()> {
469        // Validate the certificate signature against the CA's public key
470        let ca_public_key = cert_message.ca_certificate.public_key()?;
471        cert_message.node_certificate.validate(&ca_public_key)?;
472
473        // Verify the certificate is for this node
474        let node_id = self.get_node_id();
475        let dns_safe_node_id = self.dns_safe_node_id(&node_id);
476        //let expected_subject = format!("CN={dns_safe_node_id},O=Runar Node,C=US");
477        if !cert_message
478            .node_certificate
479            .subject()
480            .contains(&dns_safe_node_id)
481        {
482            return Err(KeyError::CertificateValidationError(
483                "Certificate subject doesn't match node ID".to_string(),
484            ));
485        }
486
487        // Install the certificates
488        self.node_certificate = Some(cert_message.node_certificate);
489        self.ca_certificate = Some(cert_message.ca_certificate.clone());
490
491        // Create certificate validator
492        self.certificate_validator =
493            Some(CertificateValidator::new(vec![cert_message.ca_certificate]));
494
495        self.certificate_status = CertificateStatus::Valid;
496
497        Ok(())
498    }
499
500    /// Get QUIC-compatible certificate configuration
501    pub fn get_quic_certificate_config(&self) -> Result<QuicCertificateConfig> {
502        let node_cert = self.node_certificate.as_ref().ok_or_else(|| {
503            KeyError::CertificateNotFound("Node certificate not installed".to_string())
504        })?;
505
506        let ca_cert = self.ca_certificate.as_ref().ok_or_else(|| {
507            KeyError::CertificateNotFound("CA certificate not installed".to_string())
508        })?;
509
510        let validator = self.certificate_validator.as_ref().ok_or_else(|| {
511            KeyError::InvalidOperation("Certificate validator not initialized".to_string())
512        })?;
513
514        // Create certificate chain (node cert + CA cert)
515        let certificate_chain = vec![
516            node_cert.to_rustls_certificate(),
517            ca_cert.to_rustls_certificate(),
518        ];
519
520        // Get private key for TLS
521        let private_key = self.node_key_pair.to_rustls_private_key()?;
522
523        Ok(QuicCertificateConfig {
524            certificate_chain,
525            private_key,
526            certificate_validator: validator.clone(),
527        })
528    }
529
530    /// Validate peer certificate during QUIC handshake
531    pub fn validate_peer_certificate(&self, peer_cert: &X509Certificate) -> Result<()> {
532        let validator = self.certificate_validator.as_ref().ok_or_else(|| {
533            KeyError::InvalidOperation("Certificate validator not initialized".to_string())
534        })?;
535
536        validator.validate_certificate(peer_cert)
537    }
538
539    /// Install network key from mobile with ECIES decryption
540    pub fn install_network_key(&mut self, network_key_message: NetworkKeyMessage) -> Result<()> {
541        // Decrypt the ECIES-wrapped raw 32-byte scalar using the node's agreement key
542        let encrypted_network_key = &network_key_message.encrypted_network_key;
543        let decrypted_scalar =
544            self.decrypt_key_with_ecdsa(encrypted_network_key, &self.node_key_pair)?;
545
546        if decrypted_scalar.len() != 32 {
547            return Err(KeyError::InvalidKeyFormat(
548                "Invalid network scalar length".to_string(),
549            ));
550        }
551
552        // Build an agreement secret from the scalar and store as network public id
553        use p256::SecretKey as P256SecretKey;
554        let agr = P256SecretKey::from_slice(&decrypted_scalar)
555            .map_err(|e| KeyError::InvalidKeyFormat(format!("Invalid network scalar: {e}")))?;
556
557        // Store under its public key ID
558        let network_public_key_bytes = agr.public_key().to_encoded_point(false).as_bytes().to_vec();
559        let network_public_key = compact_id(&network_public_key_bytes);
560        log_debug!(
561            self.logger,
562            "Installed network agreement key id={network_public_key}"
563        );
564        // Store under its public key ID
565        // Store agreement secret under its id
566        self.network_agreements
567            .insert(network_public_key.clone(), agr);
568
569        log_info!(
570            self.logger,
571            "Network agreement scalar installed for network: {network_public_key}"
572        );
573
574        Ok(())
575    }
576
577    /// Get network agreement key for decryption
578    pub fn get_network_agreement(&self, network_id: &str) -> Result<&P256SecretKey> {
579        self.network_agreements.get(network_id).ok_or_else(|| {
580            KeyError::KeyNotFound(format!(
581                "Network key pair not found for network: {network_id}"
582            ))
583        })
584    }
585
586    pub fn get_network_public_key(&self, network_id: &str) -> Result<Vec<u8>> {
587        // Check both network_data_keys and network_public_keys
588        if let Some(network_key) = self.network_agreements.get(network_id) {
589            Ok(network_key
590                .public_key()
591                .to_encoded_point(false)
592                .as_bytes()
593                .to_vec())
594        } else if let Some(network_public_key) = self.network_public_keys.get(network_id) {
595            Ok(network_public_key.clone())
596        } else {
597            Err(KeyError::KeyNotFound(format!(
598                "Network public key not found for network: {network_id}"
599            )))
600        }
601    }
602
603    /// Encrypt data for network transmission
604    pub fn encrypt_for_network(
605        &self,
606        data: &[u8],
607        network_id: &str,
608    ) -> Result<EnvelopeEncryptedData> {
609        // Use envelope encryption with just this network
610        let envelope_data = NodeKeyManager::encrypt_with_envelope(
611            self,
612            data,
613            Some(&network_id.to_string()),
614            vec![],
615        )?;
616        // Return just the encrypted data for compatibility
617        Ok(envelope_data)
618    }
619
620    /// Decrypt network data
621    pub fn decrypt_network_data(&self, envelope_data: &EnvelopeEncryptedData) -> Result<Vec<u8>> {
622        let network_id = envelope_data
623            .network_id
624            .as_ref()
625            .ok_or_else(|| KeyError::DecryptionError("Envelope missing network_id".to_string()))?;
626
627        let network_agreement = self.get_network_agreement(network_id)?;
628
629        let encrypted_envelope_key = &envelope_data.network_encrypted_key;
630
631        let decrypted_envelope_key =
632            self.decrypt_key_with_agreement(encrypted_envelope_key, network_agreement)?;
633
634        let decrypted_data = self
635            .decrypt_with_symmetric_key(&envelope_data.encrypted_data, &decrypted_envelope_key)?;
636
637        Ok(decrypted_data)
638
639        // // Use the network key's private key bytes as symmetric decryption key
640        // let network_private_key = network_key_pair.private_key_der().map_err(|e| {
641        //     KeyError::DecryptionError(format!("Failed to get network private key: {e}"))
642        // })?;
643
644        // // Derive decryption key from network private key using SHA256 (same as encryption)
645        // use sha2::{Digest, Sha256};
646        // let mut hasher = Sha256::new();
647        // hasher.update(&network_private_key);
648        // hasher.update(b"runar-network-encryption");
649        // let decryption_key = hasher.finalize();
650
651        // // Decrypt using AES-GCM
652        // self.decrypt_with_symmetric_key(encrypted_data, &decryption_key)
653    }
654
655    /// Check certificate status with proper cryptographic validation
656    pub fn get_certificate_status(&self) -> CertificateStatus {
657        // Check if certificate is installed
658        if let Some(cert) = &self.node_certificate {
659            if let Some(_ca_cert) = &self.ca_certificate {
660                // Perform actual cryptographic validation
661                if let Some(validator) = &self.certificate_validator {
662                    match validator.validate_certificate(cert) {
663                        Ok(()) => {
664                            log_debug!(self.logger, "Certificate validation successful");
665                            return CertificateStatus::Valid;
666                        }
667                        Err(e) => {
668                            log_warn!(self.logger, "Certificate validation failed: {e}");
669                            return CertificateStatus::Invalid;
670                        }
671                    }
672                } else {
673                    log_warn!(self.logger, "Certificate validator not initialized");
674                    return CertificateStatus::Invalid;
675                }
676            }
677            return CertificateStatus::Invalid;
678        }
679
680        self.certificate_status.clone()
681    }
682
683    /// Get certificate information
684    pub fn get_certificate_info(&self) -> Option<NodeCertificateInfo> {
685        if let (Some(node_cert), Some(ca_cert)) = (&self.node_certificate, &self.ca_certificate) {
686            Some(NodeCertificateInfo {
687                node_certificate_subject: node_cert.subject().to_string(),
688                node_certificate_issuer: node_cert.issuer().to_string(),
689                ca_certificate_subject: ca_cert.subject().to_string(),
690                status: self.get_certificate_status(),
691            })
692        } else {
693            None
694        }
695    }
696
697    /// Get statistics about the node key manager
698    pub fn get_statistics(&self) -> NodeKeyManagerStatistics {
699        NodeKeyManagerStatistics {
700            node_id: self.get_node_id(),
701            has_certificate: self.node_certificate.is_some(),
702            has_ca_certificate: self.ca_certificate.is_some(),
703            certificate_status: self.get_certificate_status(),
704            network_keys_count: self.network_agreements.len(),
705            node_public_key: compact_id(&self.get_node_public_key()),
706        }
707    }
708
709    /// Sign data with the node's private key
710    pub fn sign_data(&self, data: &[u8]) -> Result<Vec<u8>> {
711        use p256::ecdsa::{signature::Signer, Signature};
712
713        let signature: Signature = self.node_key_pair.signing_key().sign(data);
714        Ok(signature.to_der().as_bytes().to_vec())
715    }
716
717    /// Verify signature from another node
718    pub fn verify_peer_signature(
719        &self,
720        data: &[u8],
721        signature: &[u8],
722        peer_cert: &X509Certificate,
723    ) -> Result<()> {
724        // First validate the peer certificate
725        self.validate_peer_certificate(peer_cert)?;
726
727        // Extract public key from certificate
728        let peer_public_key = peer_cert.public_key()?;
729
730        // Verify the signature
731        use p256::ecdsa::{signature::Verifier, Signature};
732
733        let sig = Signature::from_der(signature).map_err(|e| {
734            KeyError::CertificateValidationError(format!("Invalid signature format: {e}"))
735        })?;
736
737        peer_public_key.verify(data, &sig).map_err(|e| {
738            KeyError::CertificateValidationError(format!("Signature verification failed: {e}"))
739        })?;
740
741        Ok(())
742    }
743
744    /// Encrypt a message for the mobile user using their public key (ECIES)
745    pub fn encrypt_message_for_mobile(
746        &self,
747        message: &[u8],
748        mobile_public_key: &[u8],
749    ) -> Result<Vec<u8>> {
750        let message_len = message.len();
751        log_debug!(
752            self.logger,
753            "Encrypting message for mobile ({message_len} bytes)"
754        );
755        self.encrypt_key_with_ecdsa(message, mobile_public_key)
756    }
757
758    /// Decrypt a message from the mobile user using the node's private key (ECIES)
759    pub fn decrypt_message_from_mobile(&self, encrypted_message: &[u8]) -> Result<Vec<u8>> {
760        let encrypted_message_len = encrypted_message.len();
761        log_debug!(
762            self.logger,
763            "Decrypting message from mobile ({encrypted_message_len} bytes)"
764        );
765        self.decrypt_key_with_ecdsa(encrypted_message, &self.node_key_pair)
766    }
767
768    /// Create an envelope key for per-object encryption
769    /// Envelope keys are ephemeral - generated fresh for each object
770    pub fn create_envelope_key(&self) -> Result<Vec<u8>> {
771        // Generate a fresh 32-byte symmetric key for envelope encryption
772        use rand::RngCore;
773        let mut envelope_key = [0u8; 32];
774        rand::thread_rng().fill_bytes(&mut envelope_key);
775        Ok(envelope_key.to_vec())
776    }
777
778    /// Create an envelope‐encrypted payload. For the node side we only
779    /// support network recipients – any supplied `profile_ids` will be
780    /// ignored. This signature exists solely to allow generic code (e.g.
781    /// serializer key-store adapter) to call the same method on both key
782    /// manager types without `cfg` branching.
783    pub fn encrypt_with_envelope(
784        &self,
785        data: &[u8],
786        network_id: Option<&String>,
787        profile_public_keys: Vec<Vec<u8>>,
788    ) -> crate::Result<crate::mobile::EnvelopeEncryptedData> {
789        let envelope_key = self.create_envelope_key()?;
790
791        // Encrypt data with envelope key
792        let encrypted_data = self.encrypt_with_symmetric_key(data, &envelope_key)?;
793
794        // Encrypt envelope key with network key if network_id provided
795        let mut network_encrypted_key = Vec::new();
796        if let Some(network_id) = network_id {
797            // Check both network_data_keys and network_public_keys
798            let network_public_key_bytes = self.get_network_public_key(network_id)?;
799
800            network_encrypted_key =
801                self.encrypt_key_with_ecdsa(&envelope_key, &network_public_key_bytes)?;
802        }
803
804        // Encrypt envelope key for each profile id using stored public key
805        let mut profile_encrypted_keys = HashMap::new();
806        for profile_public_key in profile_public_keys {
807            let encrypted_key = self.encrypt_key_with_ecdsa(&envelope_key, &profile_public_key)?;
808            let profile_id = compact_id(&profile_public_key);
809            profile_encrypted_keys.insert(profile_id, encrypted_key);
810        }
811
812        Ok(crate::mobile::EnvelopeEncryptedData {
813            encrypted_data,
814            network_id: network_id.cloned(),
815            network_encrypted_key,
816            profile_encrypted_keys,
817        })
818    }
819
820    /// Envelope-encrypt for a recipient network public key.
821    pub fn encrypt_for_public_key(
822        &self,
823        data: &[u8],
824        public_key: &[u8],
825    ) -> Result<crate::mobile::EnvelopeEncryptedData> {
826        let network_id = compact_id(public_key);
827        self.encrypt_with_envelope(data, Some(&network_id), Vec::new())
828    }
829
830    /// Check if the manager holds the private key for the given network public key.
831    pub fn has_public_key(&self, public_key: &[u8]) -> bool {
832        let network_id = compact_id(public_key);
833        self.network_agreements.contains_key(&network_id)
834    }
835
836    /// Install a user profile public key so the node can encrypt data for that profile
837    pub fn install_profile_public_key(&mut self, public_key: Vec<u8>) {
838        let pid = compact_id(&public_key);
839        self.profile_public_keys.insert(pid, public_key);
840    }
841}
842
843/// Certificate information for the node
844#[derive(Debug, Clone)]
845pub struct NodeCertificateInfo {
846    pub node_certificate_subject: String,
847    pub node_certificate_issuer: String,
848    pub ca_certificate_subject: String,
849    pub status: CertificateStatus,
850}
851
852/// Statistics about the node key manager
853#[derive(Debug, Clone)]
854pub struct NodeKeyManagerStatistics {
855    pub node_id: String,
856    pub has_certificate: bool,
857    pub has_ca_certificate: bool,
858    pub certificate_status: CertificateStatus,
859    pub network_keys_count: usize,
860    pub node_public_key: String,
861}
862
863/// Serializable node state for persistence
864#[derive(Debug, Clone, Serialize, Deserialize)]
865pub struct NodeKeyManagerState {
866    node_key_pair: EcdsaKeyPair,
867    node_certificate: Option<X509Certificate>,
868    ca_certificate: Option<X509Certificate>,
869    network_keys: HashMap<String, EcdsaKeyPair>,
870    /// Stored as PKCS#8 DER bytes of P-256 SecretKey
871    network_agreements: HashMap<String, Vec<u8>>,
872    network_public_keys: HashMap<String, Vec<u8>>,
873    profile_public_keys: HashMap<String, Vec<u8>>,
874    symmetric_keys: HashMap<String, Vec<u8>>,
875    storage_key: Vec<u8>,
876}
877
878impl NodeKeyManager {
879    /// Export state for persistence
880    pub fn export_state(&self) -> NodeKeyManagerState {
881        NodeKeyManagerState {
882            node_key_pair: self.node_key_pair.clone(),
883            node_certificate: self.node_certificate.clone(),
884            ca_certificate: self.ca_certificate.clone(),
885            network_keys: HashMap::new(),
886            network_agreements: self
887                .network_agreements
888                .iter()
889                .map(|(id, sk)| (id.clone(), sk.to_pkcs8_der().unwrap().as_bytes().to_vec()))
890                .collect(),
891            network_public_keys: self.network_public_keys.clone(),
892            profile_public_keys: self.profile_public_keys.clone(),
893            symmetric_keys: self.symmetric_keys.clone(),
894            storage_key: self.storage_key.clone(),
895        }
896    }
897
898    /// Import state from persistence
899    pub fn from_state(state: NodeKeyManagerState, logger: Arc<Logger>) -> Result<Self> {
900        let certificate_validator = state
901            .ca_certificate
902            .as_ref()
903            .map(|ca_cert| CertificateValidator::new(vec![ca_cert.clone()]));
904
905        let certificate_status =
906            if state.node_certificate.is_some() && state.ca_certificate.is_some() {
907                CertificateStatus::Valid
908            } else if state.node_certificate.is_some() {
909                CertificateStatus::Invalid
910            } else {
911                CertificateStatus::None
912            };
913
914        let node_id = compact_id(&state.node_key_pair.public_key_bytes());
915        logger.info(format!(
916            "Node Key Manager state imported for node: {node_id}"
917        ));
918
919        // Re-derive node agreement on import
920        let node_agreement_secret = crate::derivation::derive_agreement_from_master(
921            &state.node_key_pair.signing_key().to_bytes(),
922            b"runar-v1:node-identity:agreement",
923        )?;
924
925        Ok(Self {
926            node_key_pair: state.node_key_pair,
927            node_certificate: state.node_certificate,
928            ca_certificate: state.ca_certificate,
929            certificate_validator,
930            network_agreements: state
931                .network_agreements
932                .into_iter()
933                .filter_map(|(id, der)| P256SecretKey::from_pkcs8_der(&der).ok().map(|k| (id, k)))
934                .collect(),
935            network_public_keys: state.network_public_keys,
936            profile_public_keys: state.profile_public_keys,
937            symmetric_keys: state.symmetric_keys,
938            storage_key: state.storage_key,
939            node_agreement_secret,
940            certificate_status,
941            logger,
942        })
943    }
944}
945
946impl crate::EnvelopeCrypto for NodeKeyManager {
947    fn encrypt_with_envelope(
948        &self,
949        data: &[u8],
950        network_id: Option<&str>,
951        _profile_public_keys: Vec<Vec<u8>>,
952    ) -> crate::Result<crate::mobile::EnvelopeEncryptedData> {
953        // Nodes only support network-wide encryption.
954        self.create_envelope_for_network(data, network_id)
955    }
956
957    fn decrypt_envelope_data(
958        &self,
959        env: &crate::mobile::EnvelopeEncryptedData,
960    ) -> crate::Result<Vec<u8>> {
961        // Guard: ensure the encrypted key is present
962        if env.network_encrypted_key.is_empty() {
963            return Err(crate::error::KeyError::DecryptionError(
964                "Envelope missing network_encrypted_key".into(),
965            ));
966        }
967
968        NodeKeyManager::decrypt_envelope_data(self, env)
969    }
970}