//! Core implementation of keypair functionality. use k256::ecdsa::{SigningKey, VerifyingKey, signature::{Signer, Verifier}, Signature}; use rand::rngs::OsRng; use serde::{Serialize, Deserialize}; use std::collections::HashMap; use once_cell::sync::Lazy; use std::sync::Mutex; use sha2::{Sha256, Digest}; use super::error::CryptoError; /// A keypair for signing and verifying messages. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct KeyPair { pub name: String, #[serde(with = "verifying_key_serde")] pub verifying_key: VerifyingKey, #[serde(with = "signing_key_serde")] pub signing_key: SigningKey, } // Serialization helpers for VerifyingKey mod verifying_key_serde { use super::*; use serde::{Serializer, Deserializer}; use serde::de::{self, Visitor}; use std::fmt; pub fn serialize(key: &VerifyingKey, serializer: S) -> Result where S: Serializer, { let bytes = key.to_sec1_bytes(); serializer.serialize_bytes(&bytes) } struct VerifyingKeyVisitor; impl<'de> Visitor<'de> for VerifyingKeyVisitor { type Value = VerifyingKey; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a byte array representing a verifying key") } fn visit_bytes(self, v: &[u8]) -> Result where E: de::Error, { VerifyingKey::from_sec1_bytes(v).map_err(|_| E::custom("invalid verifying key")) } } pub fn deserialize<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_bytes(VerifyingKeyVisitor) } } // Serialization helpers for SigningKey mod signing_key_serde { use super::*; use serde::{Serializer, Deserializer}; use serde::de::{self, Visitor}; use std::fmt; pub fn serialize(key: &SigningKey, serializer: S) -> Result where S: Serializer, { let bytes = key.to_bytes(); serializer.serialize_bytes(&bytes) } struct SigningKeyVisitor; impl<'de> Visitor<'de> for SigningKeyVisitor { type Value = SigningKey; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a byte array representing a signing key") } fn visit_bytes(self, v: &[u8]) -> Result where E: de::Error, { SigningKey::from_bytes(v.into()).map_err(|_| E::custom("invalid signing key")) } } pub fn deserialize<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_bytes(SigningKeyVisitor) } } impl KeyPair { /// Creates a new keypair with the given name. pub fn new(name: &str) -> Self { let signing_key = SigningKey::random(&mut OsRng); let verifying_key = VerifyingKey::from(&signing_key); KeyPair { name: name.to_string(), verifying_key, signing_key, } } /// Gets the public key bytes. pub fn pub_key(&self) -> Vec { self.verifying_key.to_sec1_bytes().to_vec() } /// Derives a public key from a private key. pub fn pub_key_from_private(private_key: &[u8]) -> Result, CryptoError> { let signing_key = SigningKey::from_bytes(private_key.into()) .map_err(|_| CryptoError::InvalidKeyLength)?; let verifying_key = VerifyingKey::from(&signing_key); Ok(verifying_key.to_sec1_bytes().to_vec()) } /// Signs a message. pub fn sign(&self, message: &[u8]) -> Vec { let signature: Signature = self.signing_key.sign(message); signature.to_bytes().to_vec() } /// Verifies a message signature. pub fn verify(&self, message: &[u8], signature_bytes: &[u8]) -> Result { let signature = Signature::from_bytes(signature_bytes.into()) .map_err(|_| CryptoError::SignatureFormatError)?; match self.verifying_key.verify(message, &signature) { Ok(_) => Ok(true), Err(_) => Ok(false), // Verification failed, but operation was successful } } /// Verifies a message signature using only a public key. pub fn verify_with_public_key(public_key: &[u8], message: &[u8], signature_bytes: &[u8]) -> Result { let verifying_key = VerifyingKey::from_sec1_bytes(public_key) .map_err(|_| CryptoError::InvalidKeyLength)?; let signature = Signature::from_bytes(signature_bytes.into()) .map_err(|_| CryptoError::SignatureFormatError)?; match verifying_key.verify(message, &signature) { Ok(_) => Ok(true), Err(_) => Ok(false), // Verification failed, but operation was successful } } /// Encrypts a message using the recipient's public key. /// This implements ECIES (Elliptic Curve Integrated Encryption Scheme): /// 1. Generate an ephemeral keypair /// 2. Derive a shared secret using ECDH /// 3. Derive encryption key from the shared secret /// 4. Encrypt the message using symmetric encryption /// 5. Return the ephemeral public key and the ciphertext pub fn encrypt_asymmetric(&self, recipient_public_key: &[u8], message: &[u8]) -> Result, CryptoError> { // Parse recipient's public key let recipient_key = VerifyingKey::from_sec1_bytes(recipient_public_key) .map_err(|_| CryptoError::InvalidKeyLength)?; // Generate ephemeral keypair let ephemeral_signing_key = SigningKey::random(&mut OsRng); let ephemeral_public_key = VerifyingKey::from(&ephemeral_signing_key); // Derive shared secret (this is a simplified ECDH) // In a real implementation, we would use proper ECDH, but for this example: let shared_point = recipient_key.to_encoded_point(false); let shared_secret = { let mut hasher = Sha256::default(); hasher.update(ephemeral_signing_key.to_bytes()); hasher.update(shared_point.as_bytes()); hasher.finalize().to_vec() }; // Encrypt the message using the derived key let ciphertext = super::symmetric::encrypt_with_key(&shared_secret, message) .map_err(|_| CryptoError::EncryptionFailed)?; // Format: ephemeral_public_key || ciphertext let mut result = ephemeral_public_key.to_sec1_bytes().to_vec(); result.extend_from_slice(&ciphertext); Ok(result) } /// Decrypts a message using the recipient's private key. /// This is the counterpart to encrypt_asymmetric. pub fn decrypt_asymmetric(&self, ciphertext: &[u8]) -> Result, CryptoError> { // The first 33 or 65 bytes (depending on compression) are the ephemeral public key // For simplicity, we'll assume uncompressed keys (65 bytes) if ciphertext.len() <= 65 { return Err(CryptoError::DecryptionFailed); } // Extract ephemeral public key and actual ciphertext let ephemeral_public_key = &ciphertext[..65]; let actual_ciphertext = &ciphertext[65..]; // Parse ephemeral public key let sender_key = VerifyingKey::from_sec1_bytes(ephemeral_public_key) .map_err(|_| CryptoError::InvalidKeyLength)?; // Derive shared secret (simplified ECDH) let shared_point = sender_key.to_encoded_point(false); let shared_secret = { let mut hasher = Sha256::default(); hasher.update(self.signing_key.to_bytes()); hasher.update(shared_point.as_bytes()); hasher.finalize().to_vec() }; // Decrypt the message using the derived key super::symmetric::decrypt_with_key(&shared_secret, actual_ciphertext) .map_err(|_| CryptoError::DecryptionFailed) } } /// A collection of keypairs. #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct KeySpace { pub name: String, pub keypairs: HashMap, } impl KeySpace { /// Creates a new key space with the given name. pub fn new(name: &str) -> Self { KeySpace { name: name.to_string(), keypairs: HashMap::new(), } } /// Adds a new keypair to the space. pub fn add_keypair(&mut self, name: &str) -> Result<(), CryptoError> { if self.keypairs.contains_key(name) { return Err(CryptoError::KeypairAlreadyExists); } let keypair = KeyPair::new(name); self.keypairs.insert(name.to_string(), keypair); Ok(()) } /// Gets a keypair by name. pub fn get_keypair(&self, name: &str) -> Result<&KeyPair, CryptoError> { self.keypairs.get(name).ok_or(CryptoError::KeypairNotFound) } /// Lists all keypair names in the space. pub fn list_keypairs(&self) -> Vec { self.keypairs.keys().cloned().collect() } } /// Session state for the current key space and selected keypair. pub struct Session { pub current_space: Option, pub selected_keypair: Option, } impl Default for Session { fn default() -> Self { Session { current_space: None, selected_keypair: None, } } } /// Global session state. static SESSION: Lazy> = Lazy::new(|| { Mutex::new(Session::default()) }); /// Creates a new key space with the given name. pub fn create_space(name: &str) -> Result<(), CryptoError> { let mut session = SESSION.lock().unwrap(); // Create a new space let space = KeySpace::new(name); // Set as current space session.current_space = Some(space); session.selected_keypair = None; Ok(()) } /// Sets the current key space. pub fn set_current_space(space: KeySpace) -> Result<(), CryptoError> { let mut session = SESSION.lock().unwrap(); session.current_space = Some(space); session.selected_keypair = None; Ok(()) } /// Gets the current key space. pub fn get_current_space() -> Result { let session = SESSION.lock().unwrap(); session.current_space.clone().ok_or(CryptoError::NoActiveSpace) } /// Clears the current session (logout). pub fn clear_session() { let mut session = SESSION.lock().unwrap(); session.current_space = None; session.selected_keypair = None; } /// Creates a new keypair in the current space. pub fn create_keypair(name: &str) -> Result<(), CryptoError> { let mut session = SESSION.lock().unwrap(); if let Some(ref mut space) = session.current_space { if space.keypairs.contains_key(name) { return Err(CryptoError::KeypairAlreadyExists); } let keypair = KeyPair::new(name); space.keypairs.insert(name.to_string(), keypair); // Automatically select the new keypair session.selected_keypair = Some(name.to_string()); Ok(()) } else { Err(CryptoError::NoActiveSpace) } } /// Selects a keypair for use. pub fn select_keypair(name: &str) -> Result<(), CryptoError> { let mut session = SESSION.lock().unwrap(); if let Some(ref space) = session.current_space { if !space.keypairs.contains_key(name) { return Err(CryptoError::KeypairNotFound); } session.selected_keypair = Some(name.to_string()); Ok(()) } else { Err(CryptoError::NoActiveSpace) } } /// Gets the currently selected keypair. pub fn get_selected_keypair() -> Result { let session = SESSION.lock().unwrap(); if let Some(ref space) = session.current_space { if let Some(ref keypair_name) = session.selected_keypair { if let Some(keypair) = space.keypairs.get(keypair_name) { return Ok(keypair.clone()); } return Err(CryptoError::KeypairNotFound); } return Err(CryptoError::NoKeypairSelected); } Err(CryptoError::NoActiveSpace) } /// Lists all keypair names in the current space. pub fn list_keypairs() -> Result, CryptoError> { let session = SESSION.lock().unwrap(); if let Some(ref space) = session.current_space { Ok(space.keypairs.keys().cloned().collect()) } else { Err(CryptoError::NoActiveSpace) } } /// Gets the public key of the selected keypair. pub fn keypair_pub_key() -> Result, CryptoError> { let keypair = get_selected_keypair()?; Ok(keypair.pub_key()) } /// Derives a public key from a private key. pub fn derive_public_key(private_key: &[u8]) -> Result, CryptoError> { KeyPair::pub_key_from_private(private_key) } /// Signs a message with the selected keypair. pub fn keypair_sign(message: &[u8]) -> Result, CryptoError> { let keypair = get_selected_keypair()?; Ok(keypair.sign(message)) } /// Verifies a message signature with the selected keypair. pub fn keypair_verify(message: &[u8], signature_bytes: &[u8]) -> Result { let keypair = get_selected_keypair()?; keypair.verify(message, signature_bytes) } /// Verifies a message signature with a public key. pub fn verify_with_public_key(public_key: &[u8], message: &[u8], signature_bytes: &[u8]) -> Result { KeyPair::verify_with_public_key(public_key, message, signature_bytes) } /// Encrypts a message for a recipient using their public key. pub fn encrypt_asymmetric(recipient_public_key: &[u8], message: &[u8]) -> Result, CryptoError> { let keypair = get_selected_keypair()?; keypair.encrypt_asymmetric(recipient_public_key, message) } /// Decrypts a message that was encrypted with the current keypair's public key. pub fn decrypt_asymmetric(ciphertext: &[u8]) -> Result, CryptoError> { let keypair = get_selected_keypair()?; keypair.decrypt_asymmetric(ciphertext) }