Fix build issues
Signed-off-by: Lee Smet <lee.smet@hotmail.com>
This commit is contained in:
parent
a4438d63e0
commit
dfe6c91273
@ -12,7 +12,7 @@ use std::sync::Mutex;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
use crate::vault::ethereum::contract_utils::{convert_token_to_rhai, prepare_function_arguments};
|
||||
use crate::vault::{ethereum, keypair};
|
||||
use crate::vault::{ethereum, keyspace};
|
||||
|
||||
use crate::vault::symmetric::implementation as symmetric_impl;
|
||||
// Global Tokio runtime for blocking async operations
|
||||
@ -73,7 +73,7 @@ fn load_key_space(name: &str, password: &str) -> bool {
|
||||
};
|
||||
|
||||
// Set as current space
|
||||
match keypair::set_current_space(space) {
|
||||
match keyspace::set_current_space(space) {
|
||||
Ok(_) => true,
|
||||
Err(e) => {
|
||||
log::error!("Error setting current space: {}", e);
|
||||
@ -83,10 +83,10 @@ fn load_key_space(name: &str, password: &str) -> bool {
|
||||
}
|
||||
|
||||
fn create_key_space(name: &str, password: &str) -> bool {
|
||||
match keypair::session_manager::create_space(name) {
|
||||
match keyspace::session_manager::create_space(name) {
|
||||
Ok(_) => {
|
||||
// Get the current space
|
||||
match keypair::get_current_space() {
|
||||
match keyspace::get_current_space() {
|
||||
Ok(space) => {
|
||||
// Encrypt the key space
|
||||
let encrypted_space = match symmetric_impl::encrypt_key_space(&space, password)
|
||||
@ -151,7 +151,7 @@ fn create_key_space(name: &str, password: &str) -> bool {
|
||||
|
||||
// Auto-save function for internal use
|
||||
fn auto_save_key_space(password: &str) -> bool {
|
||||
match keypair::get_current_space() {
|
||||
match keyspace::get_current_space() {
|
||||
Ok(space) => {
|
||||
// Encrypt the key space
|
||||
let encrypted_space = match symmetric_impl::encrypt_key_space(&space, password) {
|
||||
@ -207,7 +207,7 @@ fn auto_save_key_space(password: &str) -> bool {
|
||||
}
|
||||
|
||||
fn encrypt_key_space(password: &str) -> String {
|
||||
match keypair::get_current_space() {
|
||||
match keyspace::get_current_space() {
|
||||
Ok(space) => match symmetric_impl::encrypt_key_space(&space, password) {
|
||||
Ok(encrypted_space) => match serde_json::to_string(&encrypted_space) {
|
||||
Ok(json) => json,
|
||||
@ -232,7 +232,7 @@ fn decrypt_key_space(encrypted: &str, password: &str) -> bool {
|
||||
match serde_json::from_str(encrypted) {
|
||||
Ok(encrypted_space) => {
|
||||
match symmetric_impl::decrypt_key_space(&encrypted_space, password) {
|
||||
Ok(space) => match keypair::set_current_space(space) {
|
||||
Ok(space) => match keyspace::set_current_space(space) {
|
||||
Ok(_) => true,
|
||||
Err(e) => {
|
||||
log::error!("Error setting current space: {}", e);
|
||||
@ -252,35 +252,35 @@ fn decrypt_key_space(encrypted: &str, password: &str) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
// Keypair management functions
|
||||
fn create_keypair(name: &str, password: &str) -> bool {
|
||||
match keypair::create_keypair(name) {
|
||||
// keyspace management functions
|
||||
fn create_keyspace(name: &str, password: &str) -> bool {
|
||||
match keyspace::create_keypair(name) {
|
||||
Ok(_) => {
|
||||
// Auto-save the key space after creating a keypair
|
||||
// Auto-save the key space after creating a keyspace
|
||||
auto_save_key_space(password)
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Error creating keypair: {}", e);
|
||||
log::error!("Error creating keyspace: {}", e);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn select_keypair(name: &str) -> bool {
|
||||
match keypair::select_keypair(name) {
|
||||
fn select_keyspace(name: &str) -> bool {
|
||||
match keyspace::select_keypair(name) {
|
||||
Ok(_) => true,
|
||||
Err(e) => {
|
||||
log::error!("Error selecting keypair: {}", e);
|
||||
log::error!("Error selecting keyspace: {}", e);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn list_keypairs() -> Vec<String> {
|
||||
match keypair::list_keypairs() {
|
||||
Ok(keypairs) => keypairs,
|
||||
fn list_keyspaces() -> Vec<String> {
|
||||
match keyspace::list_keypairs() {
|
||||
Ok(keyspaces) => keyspaces,
|
||||
Err(e) => {
|
||||
log::error!("Error listing keypairs: {}", e);
|
||||
log::error!("Error listing keyspaces: {}", e);
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
@ -289,7 +289,7 @@ fn list_keypairs() -> Vec<String> {
|
||||
// Cryptographic operations
|
||||
fn sign(message: &str) -> String {
|
||||
let message_bytes = message.as_bytes();
|
||||
match keypair::keypair_sign(message_bytes) {
|
||||
match keyspace::keypair_sign(message_bytes) {
|
||||
Ok(signature) => BASE64.encode(signature),
|
||||
Err(e) => {
|
||||
log::error!("Error signing message: {}", e);
|
||||
@ -301,7 +301,7 @@ fn sign(message: &str) -> String {
|
||||
fn verify(message: &str, signature: &str) -> bool {
|
||||
let message_bytes = message.as_bytes();
|
||||
match BASE64.decode(signature) {
|
||||
Ok(signature_bytes) => match keypair::keypair_verify(message_bytes, &signature_bytes) {
|
||||
Ok(signature_bytes) => match keyspace::keypair_verify(message_bytes, &signature_bytes) {
|
||||
Ok(is_valid) => is_valid,
|
||||
Err(e) => {
|
||||
log::error!("Error verifying signature: {}", e);
|
||||
@ -881,10 +881,10 @@ pub fn register_crypto_module(engine: &mut Engine) -> Result<(), Box<EvalAltResu
|
||||
engine.register_fn("encrypt_key_space", encrypt_key_space);
|
||||
engine.register_fn("decrypt_key_space", decrypt_key_space);
|
||||
|
||||
// Register keypair functions
|
||||
engine.register_fn("create_keypair", create_keypair);
|
||||
engine.register_fn("select_keypair", select_keypair);
|
||||
engine.register_fn("list_keypairs", list_keypairs);
|
||||
// Register keyspace functions
|
||||
engine.register_fn("create_keyspace", create_keyspace);
|
||||
engine.register_fn("select_keyspace", select_keyspace);
|
||||
engine.register_fn("list_keyspaces", list_keyspaces);
|
||||
|
||||
// Register signing/verification functions
|
||||
engine.register_fn("sign", sign);
|
||||
|
@ -4,12 +4,12 @@ use ethers::prelude::*;
|
||||
use ethers::signers::{LocalWallet, Signer, Wallet};
|
||||
use ethers::utils::hex;
|
||||
use k256::ecdsa::SigningKey;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::str::FromStr;
|
||||
use sha2::{Sha256, Digest};
|
||||
|
||||
use crate::vault::error::CryptoError;
|
||||
use crate::vault::keypair::KeyPair;
|
||||
use super::networks::NetworkConfig;
|
||||
use crate::vault::error::CryptoError;
|
||||
use crate::vault::keyspace::KeyPair;
|
||||
|
||||
/// An Ethereum wallet derived from a keypair.
|
||||
#[derive(Debug, Clone)]
|
||||
@ -24,88 +24,97 @@ impl EthereumWallet {
|
||||
pub fn from_keypair(keypair: &KeyPair, network: NetworkConfig) -> Result<Self, CryptoError> {
|
||||
// Get the private key bytes from the keypair
|
||||
let private_key_bytes = keypair.signing_key.to_bytes();
|
||||
|
||||
|
||||
// Convert to a hex string (without 0x prefix)
|
||||
let private_key_hex = hex::encode(private_key_bytes);
|
||||
|
||||
|
||||
// Create an Ethereum wallet from the private key
|
||||
let wallet = LocalWallet::from_str(&private_key_hex)
|
||||
.map_err(|_e| CryptoError::InvalidKeyLength)?
|
||||
.with_chain_id(network.chain_id);
|
||||
|
||||
|
||||
// Get the Ethereum address
|
||||
let address = wallet.address();
|
||||
|
||||
|
||||
Ok(EthereumWallet {
|
||||
address,
|
||||
wallet,
|
||||
network,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/// Creates a new Ethereum wallet from a name and keypair (deterministic derivation) for a specific network.
|
||||
pub fn from_name_and_keypair(name: &str, keypair: &KeyPair, network: NetworkConfig) -> Result<Self, CryptoError> {
|
||||
pub fn from_name_and_keypair(
|
||||
name: &str,
|
||||
keypair: &KeyPair,
|
||||
network: NetworkConfig,
|
||||
) -> Result<Self, CryptoError> {
|
||||
// Get the private key bytes from the keypair
|
||||
let private_key_bytes = keypair.signing_key.to_bytes();
|
||||
|
||||
|
||||
// Create a deterministic seed by combining name and private key
|
||||
let mut hasher = Sha256::default();
|
||||
hasher.update(name.as_bytes());
|
||||
hasher.update(&private_key_bytes);
|
||||
let seed = hasher.finalize();
|
||||
|
||||
|
||||
// Use the seed as a private key
|
||||
let private_key_hex = hex::encode(seed);
|
||||
|
||||
|
||||
// Create an Ethereum wallet from the derived private key
|
||||
let wallet = LocalWallet::from_str(&private_key_hex)
|
||||
.map_err(|_e| CryptoError::InvalidKeyLength)?
|
||||
.with_chain_id(network.chain_id);
|
||||
|
||||
|
||||
// Get the Ethereum address
|
||||
let address = wallet.address();
|
||||
|
||||
|
||||
Ok(EthereumWallet {
|
||||
address,
|
||||
wallet,
|
||||
network,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/// Creates a new Ethereum wallet from a private key for a specific network.
|
||||
pub fn from_private_key(private_key: &str, network: NetworkConfig) -> Result<Self, CryptoError> {
|
||||
pub fn from_private_key(
|
||||
private_key: &str,
|
||||
network: NetworkConfig,
|
||||
) -> Result<Self, CryptoError> {
|
||||
// Remove 0x prefix if present
|
||||
let private_key_clean = private_key.trim_start_matches("0x");
|
||||
|
||||
|
||||
// Create an Ethereum wallet from the private key
|
||||
let wallet = LocalWallet::from_str(private_key_clean)
|
||||
.map_err(|_e| CryptoError::InvalidKeyLength)?
|
||||
.with_chain_id(network.chain_id);
|
||||
|
||||
|
||||
// Get the Ethereum address
|
||||
let address = wallet.address();
|
||||
|
||||
|
||||
Ok(EthereumWallet {
|
||||
address,
|
||||
wallet,
|
||||
network,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/// Gets the Ethereum address as a string.
|
||||
pub fn address_string(&self) -> String {
|
||||
format!("{:?}", self.address)
|
||||
}
|
||||
|
||||
|
||||
/// Signs a message with the Ethereum wallet.
|
||||
pub async fn sign_message(&self, message: &[u8]) -> Result<String, CryptoError> {
|
||||
let signature = self.wallet.sign_message(message)
|
||||
let signature = self
|
||||
.wallet
|
||||
.sign_message(message)
|
||||
.await
|
||||
.map_err(|e| CryptoError::SignatureFormatError(e.to_string()))?;
|
||||
|
||||
|
||||
Ok(signature.to_string())
|
||||
}
|
||||
|
||||
|
||||
/// Gets the private key as a hex string.
|
||||
pub fn private_key_hex(&self) -> String {
|
||||
let bytes = self.wallet.signer().to_bytes();
|
||||
|
@ -1,14 +1,16 @@
|
||||
/// Implementation of keypair functionality.
|
||||
|
||||
use k256::ecdsa::{SigningKey, VerifyingKey, signature::{Signer, Verifier}, Signature};
|
||||
use k256::ecdh::EphemeralSecret;
|
||||
/// Implementation of keypair functionality.
|
||||
use k256::ecdsa::{
|
||||
signature::{Signer, Verifier},
|
||||
Signature, SigningKey, VerifyingKey,
|
||||
};
|
||||
use rand::rngs::OsRng;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::collections::HashMap;
|
||||
use sha2::{Sha256, Digest};
|
||||
|
||||
use crate::vault::symmetric::implementation;
|
||||
use crate::vault::error::CryptoError;
|
||||
use crate::vault::symmetric::implementation;
|
||||
|
||||
/// A keypair for signing and verifying messages.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@ -23,8 +25,8 @@ pub struct KeyPair {
|
||||
// Serialization helpers for VerifyingKey
|
||||
mod verifying_key_serde {
|
||||
use super::*;
|
||||
use serde::{Serializer, Deserializer};
|
||||
use serde::de::{self, Visitor};
|
||||
use serde::{Deserializer, Serializer};
|
||||
use std::fmt;
|
||||
|
||||
pub fn serialize<S>(key: &VerifyingKey, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@ -64,7 +66,7 @@ mod verifying_key_serde {
|
||||
while let Some(byte) = seq.next_element()? {
|
||||
bytes.push(byte);
|
||||
}
|
||||
|
||||
|
||||
VerifyingKey::from_sec1_bytes(&bytes).map_err(|e| {
|
||||
log::error!("Error deserializing verifying key from seq: {:?}", e);
|
||||
de::Error::custom(format!("invalid verifying key from seq: {:?}", e))
|
||||
@ -84,8 +86,8 @@ mod verifying_key_serde {
|
||||
// Serialization helpers for SigningKey
|
||||
mod signing_key_serde {
|
||||
use super::*;
|
||||
use serde::{Serializer, Deserializer};
|
||||
use serde::de::{self, Visitor};
|
||||
use serde::{Deserializer, Serializer};
|
||||
use std::fmt;
|
||||
|
||||
pub fn serialize<S>(key: &SigningKey, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@ -125,7 +127,7 @@ mod signing_key_serde {
|
||||
while let Some(byte) = seq.next_element()? {
|
||||
bytes.push(byte);
|
||||
}
|
||||
|
||||
|
||||
SigningKey::from_bytes(bytes.as_slice().into()).map_err(|e| {
|
||||
log::error!("Error deserializing signing key from seq: {:?}", e);
|
||||
de::Error::custom(format!("invalid signing key from seq: {:?}", e))
|
||||
@ -147,7 +149,7 @@ impl KeyPair {
|
||||
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,
|
||||
@ -159,7 +161,7 @@ impl KeyPair {
|
||||
pub fn pub_key(&self) -> Vec<u8> {
|
||||
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<Vec<u8>, CryptoError> {
|
||||
let signing_key = SigningKey::from_bytes(private_key.into())
|
||||
@ -178,27 +180,31 @@ impl KeyPair {
|
||||
pub fn verify(&self, message: &[u8], signature_bytes: &[u8]) -> Result<bool, CryptoError> {
|
||||
let signature = Signature::from_bytes(signature_bytes.into())
|
||||
.map_err(|e| CryptoError::SignatureFormatError(e.to_string()))?;
|
||||
|
||||
|
||||
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<bool, CryptoError> {
|
||||
let verifying_key = VerifyingKey::from_sec1_bytes(public_key)
|
||||
.map_err(|_| CryptoError::InvalidKeyLength)?;
|
||||
|
||||
pub fn verify_with_public_key(
|
||||
public_key: &[u8],
|
||||
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())
|
||||
.map_err(|e| CryptoError::SignatureFormatError(e.to_string()))?;
|
||||
|
||||
|
||||
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
|
||||
@ -206,19 +212,23 @@ impl KeyPair {
|
||||
/// 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<Vec<u8>, CryptoError> {
|
||||
pub fn encrypt_asymmetric(
|
||||
&self,
|
||||
recipient_public_key: &[u8],
|
||||
message: &[u8],
|
||||
) -> Result<Vec<u8>, 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 using ECDH
|
||||
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_key.into());
|
||||
|
||||
// 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 = {
|
||||
@ -226,46 +236,51 @@ impl KeyPair {
|
||||
hasher.update(shared_secret.raw_secret_bytes());
|
||||
hasher.finalize().to_vec()
|
||||
};
|
||||
|
||||
|
||||
// Encrypt the message using the derived key
|
||||
let ciphertext = implementation::encrypt_with_key(&encryption_key, message)
|
||||
.map_err(|e| CryptoError::EncryptionFailed(e.to_string()))?;
|
||||
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
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<Vec<u8>, 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("Ciphertext too short".to_string()));
|
||||
return Err(CryptoError::DecryptionFailed(
|
||||
"Ciphertext too short".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
// 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 using ECDH
|
||||
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_key.into());
|
||||
|
||||
// Derive decryption key from the shared secret (using the same method as encryption)
|
||||
let decryption_key = {
|
||||
let mut hasher = Sha256::default();
|
||||
hasher.update(shared_secret.raw_secret_bytes());
|
||||
hasher.finalize().to_vec()
|
||||
};
|
||||
|
||||
|
||||
// Decrypt the message using the derived key
|
||||
implementation::decrypt_with_key(&decryption_key, actual_ciphertext)
|
||||
.map_err(|e| CryptoError::DecryptionFailed(e.to_string()))
|
||||
@ -293,7 +308,7 @@ impl KeySpace {
|
||||
if self.keypairs.contains_key(name) {
|
||||
return Err(CryptoError::KeypairAlreadyExists(name.to_string()));
|
||||
}
|
||||
|
||||
|
||||
let keypair = KeyPair::new(name);
|
||||
self.keypairs.insert(name.to_string(), keypair);
|
||||
Ok(())
|
||||
@ -301,7 +316,9 @@ impl KeySpace {
|
||||
|
||||
/// Gets a keypair by name.
|
||||
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.
|
||||
@ -309,4 +326,3 @@ impl KeySpace {
|
||||
self.keypairs.keys().cloned().collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -355,7 +355,7 @@ impl KvStore {
|
||||
// Save to disk
|
||||
self.save()?;
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets the name of the store.
|
||||
|
Loading…
Reference in New Issue
Block a user