1use 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};
10use 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#[derive(Debug)]
24pub struct QuicCertificateConfig {
25 pub certificate_chain: Vec<CertificateDer<'static>>,
27 pub private_key: PrivateKeyDer<'static>,
29 pub certificate_validator: CertificateValidator,
31}
32
33#[derive(Debug, Clone, PartialEq)]
35pub enum CertificateStatus {
36 None,
38 Pending,
40 Valid,
42 Invalid,
44}
45
46pub struct NodeKeyManager {
48 node_key_pair: EcdsaKeyPair,
50 node_certificate: Option<X509Certificate>,
52 ca_certificate: Option<X509Certificate>,
54 certificate_validator: Option<CertificateValidator>,
56 network_agreements: HashMap<String, P256SecretKey>,
58
59 network_public_keys: HashMap<String, Vec<u8>>,
61
62 profile_public_keys: HashMap<String, Vec<u8>>,
64 symmetric_keys: HashMap<String, Vec<u8>>,
66 storage_key: Vec<u8>,
68 node_agreement_secret: P256SecretKey,
70 certificate_status: CertificateStatus,
72 logger: Arc<Logger>,
74}
75
76impl NodeKeyManager {
77 pub fn new(logger: Arc<Logger>) -> Result<Self> {
79 let node_key_pair = EcdsaKeyPair::new()?;
81
82 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 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 pub fn get_node_public_key(&self) -> Vec<u8> {
126 self.node_key_pair.public_key_bytes()
127 }
128
129 pub fn get_node_id(&self) -> String {
131 compact_id(&self.node_key_pair.public_key_bytes())
132 }
133
134 pub fn get_storage_key(&self) -> &[u8] {
138 &self.storage_key
139 }
140
141 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 let mut key = [0u8; 32];
149 rand::thread_rng().fill_bytes(&mut key);
150 let key_vec = key.to_vec();
151
152 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 pub fn encrypt_local_data(&self, data: &[u8]) -> Result<Vec<u8>> {
162 let storage_key = self.get_storage_key();
163
164 self.encrypt_with_symmetric_key(data, storage_key)
166 }
167
168 pub fn decrypt_local_data(&self, encrypted_data: &[u8]) -> Result<Vec<u8>> {
170 let storage_key = self.get_storage_key();
171
172 self.decrypt_with_symmetric_key(encrypted_data, storage_key)
174 }
175
176 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 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 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 let envelope_key = self.generate_envelope_key()?;
218
219 let encrypted_data = self.encrypt_with_symmetric_key(data, &envelope_key)?;
221
222 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 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 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 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 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 let ephemeral_secret = EphemeralSecret::random(&mut thread_rng());
309 let ephemeral_public = ephemeral_secret.public_key();
310
311 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 let shared_secret = ephemeral_secret.diffie_hellman(&recipient_public_key);
319 let shared_secret_bytes = shared_secret.raw_secret_bytes();
320
321 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 let encrypted_data = self.encrypt_with_symmetric_key(data, &encryption_key)?;
329
330 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 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 sha2::Sha256;
348
349 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 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 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 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 self.decrypt_with_symmetric_key(encrypted_payload, &encryption_key)
379 }
380
381 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 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 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 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 pub fn dns_safe_node_id(&self, node_id: &str) -> String {
451 node_id
452 .chars()
453 .map(|c| match c {
454 '-' => 'x', '_' => 'y', c if c.is_alphanumeric() => c, _ => 'z', })
459 .collect()
460 }
461
462 pub fn get_node_key_pair(&self) -> &EcdsaKeyPair {
464 &self.node_key_pair
465 }
466
467 pub fn install_certificate(&mut self, cert_message: NodeCertificateMessage) -> Result<()> {
469 let ca_public_key = cert_message.ca_certificate.public_key()?;
471 cert_message.node_certificate.validate(&ca_public_key)?;
472
473 let node_id = self.get_node_id();
475 let dns_safe_node_id = self.dns_safe_node_id(&node_id);
476 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 self.node_certificate = Some(cert_message.node_certificate);
489 self.ca_certificate = Some(cert_message.ca_certificate.clone());
490
491 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 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 let certificate_chain = vec![
516 node_cert.to_rustls_certificate(),
517 ca_cert.to_rustls_certificate(),
518 ];
519
520 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 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 pub fn install_network_key(&mut self, network_key_message: NetworkKeyMessage) -> Result<()> {
541 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 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 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 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 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 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 pub fn encrypt_for_network(
605 &self,
606 data: &[u8],
607 network_id: &str,
608 ) -> Result<EnvelopeEncryptedData> {
609 let envelope_data = NodeKeyManager::encrypt_with_envelope(
611 self,
612 data,
613 Some(&network_id.to_string()),
614 vec![],
615 )?;
616 Ok(envelope_data)
618 }
619
620 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 }
654
655 pub fn get_certificate_status(&self) -> CertificateStatus {
657 if let Some(cert) = &self.node_certificate {
659 if let Some(_ca_cert) = &self.ca_certificate {
660 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 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 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 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 pub fn verify_peer_signature(
719 &self,
720 data: &[u8],
721 signature: &[u8],
722 peer_cert: &X509Certificate,
723 ) -> Result<()> {
724 self.validate_peer_certificate(peer_cert)?;
726
727 let peer_public_key = peer_cert.public_key()?;
729
730 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 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 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 pub fn create_envelope_key(&self) -> Result<Vec<u8>> {
771 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 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 let encrypted_data = self.encrypt_with_symmetric_key(data, &envelope_key)?;
793
794 let mut network_encrypted_key = Vec::new();
796 if let Some(network_id) = network_id {
797 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 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 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 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 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#[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#[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#[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 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 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 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 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 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 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}