Simplify and Refactor Asymmetric Encryption/Decryption #10

Merged
MahmoudEmad merged 3 commits from development_fix_code into main 2025-05-13 13:00:16 +00:00
2 changed files with 68 additions and 42 deletions
Showing only changes of commit 809599d60c - Show all commits

View File

@ -206,7 +206,7 @@ impl RedisClientWrapper {
} }
// Select the database // Select the database
redis::cmd("SELECT").arg(self.db).execute(&mut conn); let _ = redis::cmd("SELECT").arg(self.db).exec(&mut conn);
self.initialized.store(true, Ordering::Relaxed); self.initialized.store(true, Ordering::Relaxed);

View File

@ -1,14 +1,17 @@
/// Implementation of keypair functionality.
use k256::ecdsa::{SigningKey, VerifyingKey, signature::{Signer, Verifier}, Signature};
use k256::ecdh::EphemeralSecret; use k256::ecdh::EphemeralSecret;
/// Implementation of keypair functionality.
use k256::ecdsa::{
signature::{Signer, Verifier},
Signature, SigningKey, VerifyingKey,
};
use rand::rngs::OsRng; use rand::rngs::OsRng;
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use std::collections::HashMap; use std::collections::HashMap;
use sha2::{Sha256, Digest};
use crate::vault::symmetric::implementation;
use crate::vault::error::CryptoError; use crate::vault::error::CryptoError;
use crate::vault::symmetric::implementation;
use k256::elliptic_curve::PublicKey;
/// A keypair for signing and verifying messages. /// A keypair for signing and verifying messages.
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@ -23,8 +26,8 @@ pub struct KeyPair {
// Serialization helpers for VerifyingKey // Serialization helpers for VerifyingKey
mod verifying_key_serde { mod verifying_key_serde {
use super::*; use super::*;
use serde::{Serializer, Deserializer};
use serde::de::{self, Visitor}; use serde::de::{self, Visitor};
use serde::{Deserializer, Serializer};
use std::fmt; use std::fmt;
pub fn serialize<S>(key: &VerifyingKey, serializer: S) -> Result<S::Ok, S::Error> pub fn serialize<S>(key: &VerifyingKey, serializer: S) -> Result<S::Ok, S::Error>
@ -64,7 +67,7 @@ mod verifying_key_serde {
while let Some(byte) = seq.next_element()? { while let Some(byte) = seq.next_element()? {
bytes.push(byte); bytes.push(byte);
} }
VerifyingKey::from_sec1_bytes(&bytes).map_err(|e| { VerifyingKey::from_sec1_bytes(&bytes).map_err(|e| {
log::error!("Error deserializing verifying key from seq: {:?}", e); log::error!("Error deserializing verifying key from seq: {:?}", e);
de::Error::custom(format!("invalid verifying key from seq: {:?}", e)) de::Error::custom(format!("invalid verifying key from seq: {:?}", e))
@ -84,8 +87,8 @@ mod verifying_key_serde {
// Serialization helpers for SigningKey // Serialization helpers for SigningKey
mod signing_key_serde { mod signing_key_serde {
use super::*; use super::*;
use serde::{Serializer, Deserializer};
use serde::de::{self, Visitor}; use serde::de::{self, Visitor};
use serde::{Deserializer, Serializer};
use std::fmt; use std::fmt;
pub fn serialize<S>(key: &SigningKey, serializer: S) -> Result<S::Ok, S::Error> pub fn serialize<S>(key: &SigningKey, serializer: S) -> Result<S::Ok, S::Error>
@ -125,7 +128,7 @@ mod signing_key_serde {
while let Some(byte) = seq.next_element()? { while let Some(byte) = seq.next_element()? {
bytes.push(byte); bytes.push(byte);
} }
SigningKey::from_bytes(bytes.as_slice().into()).map_err(|e| { SigningKey::from_bytes(bytes.as_slice().into()).map_err(|e| {
log::error!("Error deserializing signing key from seq: {:?}", e); log::error!("Error deserializing signing key from seq: {:?}", e);
de::Error::custom(format!("invalid signing key from seq: {:?}", e)) de::Error::custom(format!("invalid signing key from seq: {:?}", e))
@ -147,7 +150,7 @@ impl KeyPair {
pub fn new(name: &str) -> Self { pub fn new(name: &str) -> Self {
let signing_key = SigningKey::random(&mut OsRng); let signing_key = SigningKey::random(&mut OsRng);
let verifying_key = VerifyingKey::from(&signing_key); let verifying_key = VerifyingKey::from(&signing_key);
KeyPair { KeyPair {
name: name.to_string(), name: name.to_string(),
verifying_key, verifying_key,
@ -159,7 +162,7 @@ impl KeyPair {
pub fn pub_key(&self) -> Vec<u8> { pub fn pub_key(&self) -> Vec<u8> {
self.verifying_key.to_sec1_bytes().to_vec() self.verifying_key.to_sec1_bytes().to_vec()
} }
/// Derives a public key from a private key. /// Derives a public key from a private key.
pub fn pub_key_from_private(private_key: &[u8]) -> Result<Vec<u8>, CryptoError> { pub fn pub_key_from_private(private_key: &[u8]) -> Result<Vec<u8>, CryptoError> {
let signing_key = SigningKey::from_bytes(private_key.into()) let signing_key = SigningKey::from_bytes(private_key.into())
@ -178,27 +181,31 @@ impl KeyPair {
pub fn verify(&self, message: &[u8], signature_bytes: &[u8]) -> Result<bool, CryptoError> { pub fn verify(&self, message: &[u8], signature_bytes: &[u8]) -> Result<bool, CryptoError> {
let signature = Signature::from_bytes(signature_bytes.into()) let signature = Signature::from_bytes(signature_bytes.into())
.map_err(|e| CryptoError::SignatureFormatError(e.to_string()))?; .map_err(|e| CryptoError::SignatureFormatError(e.to_string()))?;
match self.verifying_key.verify(message, &signature) { match self.verifying_key.verify(message, &signature) {
Ok(_) => Ok(true), Ok(_) => Ok(true),
Err(_) => Ok(false), // Verification failed, but operation was successful Err(_) => Ok(false), // Verification failed, but operation was successful
} }
} }
/// Verifies a message signature using only a public key. /// Verifies a message signature using only a public key.
pub fn verify_with_public_key(public_key: &[u8], message: &[u8], signature_bytes: &[u8]) -> Result<bool, CryptoError> { pub fn verify_with_public_key(
let verifying_key = VerifyingKey::from_sec1_bytes(public_key) public_key: &[u8],
.map_err(|_| CryptoError::InvalidKeyLength)?; message: &[u8],
signature_bytes: &[u8],
) -> Result<bool, CryptoError> {
let verifying_key =
VerifyingKey::from_sec1_bytes(public_key).map_err(|_| CryptoError::InvalidKeyLength)?;
let signature = Signature::from_bytes(signature_bytes.into()) let signature = Signature::from_bytes(signature_bytes.into())
.map_err(|e| CryptoError::SignatureFormatError(e.to_string()))?; .map_err(|e| CryptoError::SignatureFormatError(e.to_string()))?;
match verifying_key.verify(message, &signature) { match verifying_key.verify(message, &signature) {
Ok(_) => Ok(true), Ok(_) => Ok(true),
Err(_) => Ok(false), // Verification failed, but operation was successful Err(_) => Ok(false), // Verification failed, but operation was successful
} }
} }
/// Encrypts a message using the recipient's public key. /// Encrypts a message using the recipient's public key.
/// This implements ECIES (Elliptic Curve Integrated Encryption Scheme): /// This implements ECIES (Elliptic Curve Integrated Encryption Scheme):
/// 1. Generate an ephemeral keypair /// 1. Generate an ephemeral keypair
@ -206,66 +213,84 @@ impl KeyPair {
/// 3. Derive encryption key from the shared secret /// 3. Derive encryption key from the shared secret
/// 4. Encrypt the message using symmetric encryption /// 4. Encrypt the message using symmetric encryption
/// 5. Return the ephemeral public key and the ciphertext /// 5. Return the ephemeral public key and the ciphertext
pub fn encrypt_asymmetric(&self, recipient_public_key: &[u8], message: &[u8]) -> Result<Vec<u8>, CryptoError> { pub fn encrypt_asymmetric(
&self,
recipient_public_key: &[u8],
message: &[u8],
) -> Result<Vec<u8>, CryptoError> {
// Parse recipient's public key // Parse recipient's public key
let recipient_key = VerifyingKey::from_sec1_bytes(recipient_public_key) let recipient_key = VerifyingKey::from_sec1_bytes(recipient_public_key)
.map_err(|_| CryptoError::InvalidKeyLength)?; .map_err(|_| CryptoError::InvalidKeyLength)?;
// Convert ecdsa VerifyingKey to k256 PublicKey
let recipient_public_key_k256 =
PublicKey::from_sec1_bytes(&recipient_key.to_encoded_point(false).as_bytes())
.map_err(|_| CryptoError::InvalidKeyLength)?;
// Generate ephemeral keypair // Generate ephemeral keypair
let ephemeral_signing_key = SigningKey::random(&mut OsRng); let ephemeral_signing_key = SigningKey::random(&mut OsRng);
let ephemeral_public_key = VerifyingKey::from(&ephemeral_signing_key); let ephemeral_public_key = VerifyingKey::from(&ephemeral_signing_key);
// Derive shared secret using ECDH // Derive shared secret using ECDH
let ephemeral_secret = EphemeralSecret::random(&mut OsRng); let ephemeral_secret = EphemeralSecret::random(&mut OsRng);
let shared_secret = ephemeral_secret.diffie_hellman(&recipient_key.to_public_key()); let shared_secret = ephemeral_secret.diffie_hellman(&recipient_public_key_k256);
// Derive encryption key from the shared secret (e.g., using HKDF or hashing) // Derive encryption key from the shared secret (e.g., using HKDF or hashing)
// For simplicity, we'll hash the shared secret here
let encryption_key = { let encryption_key = {
let mut hasher = Sha256::default(); let mut hasher = Sha256::default();
hasher.update(shared_secret.raw_secret_bytes()); hasher.update(shared_secret.raw_secret_bytes());
hasher.finalize().to_vec() hasher.finalize().to_vec()
}; };
// Encrypt the message using the derived key // Encrypt the message using the derived key
let ciphertext = implementation::encrypt_with_key(&encryption_key, message) let ciphertext = implementation::encrypt_with_key(&encryption_key, message)
.map_err(|e| CryptoError::EncryptionFailed(e.to_string()))?; .map_err(|e| CryptoError::EncryptionFailed(e.to_string()))?;
// Format: ephemeral_public_key || ciphertext // Format: ephemeral_public_key || ciphertext
let mut result = ephemeral_public_key.to_encoded_point(false).as_bytes().to_vec(); let mut result = ephemeral_public_key
.to_encoded_point(false)
.as_bytes()
.to_vec();
result.extend_from_slice(&ciphertext); result.extend_from_slice(&ciphertext);
Ok(result) Ok(result)
} }
/// Decrypts a message using the recipient's private key. /// Decrypts a message using the recipient's private key.
/// This is the counterpart to encrypt_asymmetric. /// This is the counterpart to encrypt_asymmetric.
pub fn decrypt_asymmetric(&self, ciphertext: &[u8]) -> Result<Vec<u8>, CryptoError> { pub fn decrypt_asymmetric(&self, ciphertext: &[u8]) -> Result<Vec<u8>, CryptoError> {
// The first 33 or 65 bytes (depending on compression) are the ephemeral public key // The first 33 or 65 bytes (depending on compression) are the ephemeral public key
// For simplicity, we'll assume uncompressed keys (65 bytes) // For simplicity, we'll assume uncompressed keys (65 bytes)
if ciphertext.len() <= 65 { if ciphertext.len() <= 65 {
return Err(CryptoError::DecryptionFailed("Ciphertext too short".to_string())); return Err(CryptoError::DecryptionFailed(
"Ciphertext too short".to_string(),
));
} }
// Extract ephemeral public key and actual ciphertext // Extract ephemeral public key and actual ciphertext
let ephemeral_public_key = &ciphertext[..65]; let ephemeral_public_key = &ciphertext[..65];
let actual_ciphertext = &ciphertext[65..]; let actual_ciphertext = &ciphertext[65..];
// Parse ephemeral public key // Parse ephemeral public key
let sender_key = VerifyingKey::from_sec1_bytes(ephemeral_public_key) let sender_key = VerifyingKey::from_sec1_bytes(ephemeral_public_key)
.map_err(|_| CryptoError::InvalidKeyLength)?; .map_err(|_| CryptoError::InvalidKeyLength)?;
// Convert ecdsa VerifyingKey to k256 PublicKey
let sender_public_key_k256 =
PublicKey::from_sec1_bytes(&sender_key.to_encoded_point(false).as_bytes())
.map_err(|_| CryptoError::InvalidKeyLength)?;
// Derive shared secret using ECDH // Derive shared secret using ECDH
let recipient_secret = EphemeralSecret::random(&mut OsRng); let recipient_secret = EphemeralSecret::random(&mut OsRng);
let shared_secret = recipient_secret.diffie_hellman(&sender_key.to_public_key()); let shared_secret = recipient_secret.diffie_hellman(&sender_public_key_k256);
// Derive decryption key from the shared secret (using the same method as encryption) // Derive decryption key from the shared secret (using the same method as encryption)
let decryption_key = { let decryption_key = {
let mut hasher = Sha256::default(); let mut hasher = Sha256::default();
hasher.update(shared_secret.raw_secret_bytes()); hasher.update(shared_secret.raw_secret_bytes());
hasher.finalize().to_vec() hasher.finalize().to_vec()
}; };
// Decrypt the message using the derived key // Decrypt the message using the derived key
implementation::decrypt_with_key(&decryption_key, actual_ciphertext) implementation::decrypt_with_key(&decryption_key, actual_ciphertext)
.map_err(|e| CryptoError::DecryptionFailed(e.to_string())) .map_err(|e| CryptoError::DecryptionFailed(e.to_string()))
@ -293,7 +318,7 @@ impl KeySpace {
if self.keypairs.contains_key(name) { if self.keypairs.contains_key(name) {
return Err(CryptoError::KeypairAlreadyExists(name.to_string())); return Err(CryptoError::KeypairAlreadyExists(name.to_string()));
} }
let keypair = KeyPair::new(name); let keypair = KeyPair::new(name);
self.keypairs.insert(name.to_string(), keypair); self.keypairs.insert(name.to_string(), keypair);
Ok(()) Ok(())
@ -301,7 +326,9 @@ impl KeySpace {
/// Gets a keypair by name. /// Gets a keypair by name.
pub fn get_keypair(&self, name: &str) -> Result<&KeyPair, CryptoError> { pub fn get_keypair(&self, name: &str) -> Result<&KeyPair, CryptoError> {
self.keypairs.get(name).ok_or(CryptoError::KeypairNotFound(name.to_string())) self.keypairs
.get(name)
.ok_or(CryptoError::KeypairNotFound(name.to_string()))
} }
/// Lists all keypair names in the space. /// Lists all keypair names in the space.
@ -309,4 +336,3 @@ impl KeySpace {
self.keypairs.keys().cloned().collect() self.keypairs.keys().cloned().collect()
} }
} }