...
This commit is contained in:
173
src/api/ethereum.rs
Normal file
173
src/api/ethereum.rs
Normal file
@@ -0,0 +1,173 @@
|
||||
//! Public API for Ethereum operations.
|
||||
|
||||
use crate::core::ethereum;
|
||||
use crate::core::error::CryptoError;
|
||||
use ethers::prelude::*;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
/// Creates an Ethereum wallet from the currently selected keypair.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Ok(())` if the wallet was created successfully.
|
||||
/// * `Err(CryptoError::NoActiveSpace)` if no space is active.
|
||||
/// * `Err(CryptoError::NoKeypairSelected)` if no keypair is selected.
|
||||
/// * `Err(CryptoError::KeypairNotFound)` if the selected keypair was not found.
|
||||
/// * `Err(CryptoError::InvalidKeyLength)` if the keypair's private key is invalid for Ethereum.
|
||||
pub fn create_ethereum_wallet() -> Result<(), CryptoError> {
|
||||
ethereum::create_ethereum_wallet()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Creates an Ethereum wallet from a name and the currently selected keypair.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `name` - The name to use for deterministic derivation.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Ok(())` if the wallet was created successfully.
|
||||
/// * `Err(CryptoError)` if an error occurred.
|
||||
pub fn create_ethereum_wallet_from_name(name: &str) -> Result<(), CryptoError> {
|
||||
ethereum::create_ethereum_wallet_from_name(name)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Creates an Ethereum wallet from a private key.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `private_key` - The private key as a hex string (with or without 0x prefix).
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Ok(())` if the wallet was created successfully.
|
||||
/// * `Err(CryptoError)` if an error occurred.
|
||||
pub fn create_ethereum_wallet_from_private_key(private_key: &str) -> Result<(), CryptoError> {
|
||||
ethereum::create_ethereum_wallet_from_private_key(private_key)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets the Ethereum address of the current wallet.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Ok(String)` containing the Ethereum address.
|
||||
/// * `Err(CryptoError::NoEthereumWallet)` if no Ethereum wallet is available.
|
||||
pub fn get_ethereum_address() -> Result<String, CryptoError> {
|
||||
let wallet = ethereum::get_current_ethereum_wallet()?;
|
||||
Ok(wallet.address_string())
|
||||
}
|
||||
|
||||
/// Gets the Ethereum private key as a hex string.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Ok(String)` containing the Ethereum private key as a hex string.
|
||||
/// * `Err(CryptoError::NoEthereumWallet)` if no Ethereum wallet is available.
|
||||
pub fn get_ethereum_private_key() -> Result<String, CryptoError> {
|
||||
let wallet = ethereum::get_current_ethereum_wallet()?;
|
||||
Ok(wallet.private_key_hex())
|
||||
}
|
||||
|
||||
/// Signs a message with the Ethereum wallet.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `message` - The message to sign.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Ok(String)` containing the signature.
|
||||
/// * `Err(CryptoError::NoEthereumWallet)` if no Ethereum wallet is available.
|
||||
/// * `Err(CryptoError::SignatureFormatError)` if signing fails.
|
||||
pub async fn sign_ethereum_message(message: &[u8]) -> Result<String, CryptoError> {
|
||||
let wallet = ethereum::get_current_ethereum_wallet()?;
|
||||
wallet.sign_message(message).await
|
||||
}
|
||||
|
||||
/// Formats an Ethereum balance for display.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `balance_hex` - The balance as a hex string.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `String` containing the formatted balance.
|
||||
pub fn format_eth_balance(balance_hex: &str) -> String {
|
||||
let balance = U256::from_str_radix(balance_hex.trim_start_matches("0x"), 16)
|
||||
.unwrap_or_default();
|
||||
ethereum::format_eth_balance(balance)
|
||||
}
|
||||
|
||||
/// Gets the balance of an Ethereum address.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `address_str` - The Ethereum address as a string.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Ok(String)` containing the balance as a hex string.
|
||||
/// * `Err(CryptoError)` if getting the balance fails.
|
||||
pub async fn get_ethereum_balance(address_str: &str) -> Result<String, CryptoError> {
|
||||
// Create a provider
|
||||
let provider = ethereum::create_gnosis_provider()?;
|
||||
|
||||
// Parse the address
|
||||
let address = address_str.parse::<Address>()
|
||||
.map_err(|_| CryptoError::InvalidEthereumAddress)?;
|
||||
|
||||
// Get the balance
|
||||
let balance = ethereum::get_balance(&provider, address).await?;
|
||||
|
||||
// Return the balance as a hex string
|
||||
Ok(format!("0x{:x}", balance))
|
||||
}
|
||||
|
||||
/// Sends Ethereum from the current wallet to another address.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `to_address` - The recipient's Ethereum address as a string.
|
||||
/// * `amount_eth` - The amount to send in ETH (as a string).
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Ok(String)` containing the transaction hash.
|
||||
/// * `Err(CryptoError)` if sending fails.
|
||||
pub async fn send_ethereum(
|
||||
to_address: &str,
|
||||
amount_eth: &str,
|
||||
) -> Result<String, CryptoError> {
|
||||
// Create a provider
|
||||
let provider = ethereum::create_gnosis_provider()?;
|
||||
|
||||
// Get the current wallet
|
||||
let wallet = ethereum::get_current_ethereum_wallet()?;
|
||||
|
||||
// Parse the recipient address
|
||||
let to = to_address.parse::<Address>()
|
||||
.map_err(|_| CryptoError::InvalidEthereumAddress)?;
|
||||
|
||||
// Parse the amount
|
||||
let amount_eth_float = amount_eth.parse::<f64>()
|
||||
.map_err(|_| CryptoError::Other("Invalid amount".to_string()))?;
|
||||
|
||||
// Convert ETH to Wei
|
||||
let amount_wei = (amount_eth_float * 1_000_000_000_000_000_000.0) as u128;
|
||||
let amount = U256::from(amount_wei);
|
||||
|
||||
// Send the transaction
|
||||
let tx_hash = ethereum::send_eth(&wallet, &provider, to, amount).await?;
|
||||
|
||||
// Return the transaction hash
|
||||
Ok(format!("0x{:x}", tx_hash))
|
||||
}
|
||||
|
||||
/// Clears all Ethereum wallets.
|
||||
pub fn clear_ethereum_wallets() {
|
||||
ethereum::clear_ethereum_wallets();
|
||||
}
|
@@ -2,6 +2,7 @@
|
||||
|
||||
pub mod keypair;
|
||||
pub mod symmetric;
|
||||
pub mod ethereum;
|
||||
|
||||
// Re-export commonly used items for external users
|
||||
// (Keeping this even though it's currently unused, as it's good practice for public APIs)
|
||||
|
@@ -34,6 +34,12 @@ pub enum CryptoError {
|
||||
InvalidPassword,
|
||||
/// Error during serialization or deserialization.
|
||||
SerializationError,
|
||||
/// No Ethereum wallet is available.
|
||||
NoEthereumWallet,
|
||||
/// Ethereum transaction failed.
|
||||
EthereumTransactionFailed,
|
||||
/// Invalid Ethereum address.
|
||||
InvalidEthereumAddress,
|
||||
/// Other error with description.
|
||||
#[allow(dead_code)]
|
||||
Other(String),
|
||||
@@ -57,6 +63,9 @@ impl std::fmt::Display for CryptoError {
|
||||
CryptoError::SpaceAlreadyExists => write!(f, "Space already exists"),
|
||||
CryptoError::InvalidPassword => write!(f, "Invalid password"),
|
||||
CryptoError::SerializationError => write!(f, "Serialization error"),
|
||||
CryptoError::NoEthereumWallet => write!(f, "No Ethereum wallet available"),
|
||||
CryptoError::EthereumTransactionFailed => write!(f, "Ethereum transaction failed"),
|
||||
CryptoError::InvalidEthereumAddress => write!(f, "Invalid Ethereum address"),
|
||||
CryptoError::Other(s) => write!(f, "Crypto error: {}", s),
|
||||
}
|
||||
}
|
||||
@@ -82,6 +91,9 @@ pub fn error_to_status_code(err: CryptoError) -> i32 {
|
||||
CryptoError::SpaceAlreadyExists => -13,
|
||||
CryptoError::InvalidPassword => -14,
|
||||
CryptoError::SerializationError => -15,
|
||||
CryptoError::NoEthereumWallet => -16,
|
||||
CryptoError::EthereumTransactionFailed => -17,
|
||||
CryptoError::InvalidEthereumAddress => -18,
|
||||
CryptoError::Other(_) => -99,
|
||||
}
|
||||
}
|
228
src/core/ethereum.rs
Normal file
228
src/core/ethereum.rs
Normal file
@@ -0,0 +1,228 @@
|
||||
//! Core implementation of Ethereum functionality.
|
||||
|
||||
use ethers::prelude::*;
|
||||
use ethers::signers::{LocalWallet, Signer, Wallet};
|
||||
use ethers::utils::hex;
|
||||
use k256::ecdsa::SigningKey;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Mutex;
|
||||
use once_cell::sync::Lazy;
|
||||
use sha2::{Sha256, Digest};
|
||||
|
||||
use super::error::CryptoError;
|
||||
use super::keypair::KeyPair;
|
||||
|
||||
// Gnosis Chain configuration
|
||||
pub const GNOSIS_CHAIN_ID: u64 = 100;
|
||||
pub const GNOSIS_RPC_URL: &str = "https://rpc.gnosis.gateway.fm";
|
||||
pub const GNOSIS_EXPLORER: &str = "https://gnosisscan.io";
|
||||
|
||||
/// An Ethereum wallet derived from a keypair.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EthereumWallet {
|
||||
pub address: Address,
|
||||
pub wallet: Wallet<SigningKey>,
|
||||
}
|
||||
|
||||
impl EthereumWallet {
|
||||
/// Creates a new Ethereum wallet from a keypair.
|
||||
pub fn from_keypair(keypair: &KeyPair) -> 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(|_| CryptoError::InvalidKeyLength)?
|
||||
.with_chain_id(GNOSIS_CHAIN_ID);
|
||||
|
||||
// Get the Ethereum address
|
||||
let address = wallet.address();
|
||||
|
||||
Ok(EthereumWallet {
|
||||
address,
|
||||
wallet,
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new Ethereum wallet from a name and keypair (deterministic derivation).
|
||||
pub fn from_name_and_keypair(name: &str, keypair: &KeyPair) -> 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(|_| CryptoError::InvalidKeyLength)?
|
||||
.with_chain_id(GNOSIS_CHAIN_ID);
|
||||
|
||||
// Get the Ethereum address
|
||||
let address = wallet.address();
|
||||
|
||||
Ok(EthereumWallet {
|
||||
address,
|
||||
wallet,
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new Ethereum wallet from a private key.
|
||||
pub fn from_private_key(private_key: &str) -> 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(|_| CryptoError::InvalidKeyLength)?
|
||||
.with_chain_id(GNOSIS_CHAIN_ID);
|
||||
|
||||
// Get the Ethereum address
|
||||
let address = wallet.address();
|
||||
|
||||
Ok(EthereumWallet {
|
||||
address,
|
||||
wallet,
|
||||
})
|
||||
}
|
||||
|
||||
/// 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)
|
||||
.await
|
||||
.map_err(|_| CryptoError::SignatureFormatError)?;
|
||||
|
||||
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();
|
||||
hex::encode(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
/// Global storage for Ethereum wallets.
|
||||
static ETH_WALLETS: Lazy<Mutex<Vec<EthereumWallet>>> = Lazy::new(|| {
|
||||
Mutex::new(Vec::new())
|
||||
});
|
||||
|
||||
/// Creates an Ethereum wallet from the currently selected keypair.
|
||||
pub fn create_ethereum_wallet() -> Result<EthereumWallet, CryptoError> {
|
||||
// Get the currently selected keypair
|
||||
let keypair = super::keypair::get_selected_keypair()?;
|
||||
|
||||
// Create an Ethereum wallet from the keypair
|
||||
let wallet = EthereumWallet::from_keypair(&keypair)?;
|
||||
|
||||
// Store the wallet
|
||||
let mut wallets = ETH_WALLETS.lock().unwrap();
|
||||
wallets.push(wallet.clone());
|
||||
|
||||
Ok(wallet)
|
||||
}
|
||||
|
||||
/// Gets the current Ethereum wallet.
|
||||
pub fn get_current_ethereum_wallet() -> Result<EthereumWallet, CryptoError> {
|
||||
let wallets = ETH_WALLETS.lock().unwrap();
|
||||
|
||||
if wallets.is_empty() {
|
||||
return Err(CryptoError::NoKeypairSelected);
|
||||
}
|
||||
|
||||
Ok(wallets.last().unwrap().clone())
|
||||
}
|
||||
|
||||
/// Clears all Ethereum wallets.
|
||||
pub fn clear_ethereum_wallets() {
|
||||
let mut wallets = ETH_WALLETS.lock().unwrap();
|
||||
wallets.clear();
|
||||
}
|
||||
|
||||
/// Formats an Ethereum balance for display.
|
||||
pub fn format_eth_balance(balance: U256) -> String {
|
||||
let wei = balance.as_u128();
|
||||
let eth = wei as f64 / 1_000_000_000_000_000_000.0;
|
||||
format!("{:.6} ETH", eth)
|
||||
}
|
||||
|
||||
/// Gets the balance of an Ethereum address.
|
||||
pub async fn get_balance(provider: &Provider<Http>, address: Address) -> Result<U256, CryptoError> {
|
||||
provider.get_balance(address, None)
|
||||
.await
|
||||
.map_err(|_| CryptoError::Other("Failed to get balance".to_string()))
|
||||
}
|
||||
|
||||
/// Sends Ethereum from one address to another.
|
||||
pub async fn send_eth(
|
||||
wallet: &EthereumWallet,
|
||||
provider: &Provider<Http>,
|
||||
to: Address,
|
||||
amount: U256,
|
||||
) -> Result<H256, CryptoError> {
|
||||
// Create a client with the wallet
|
||||
let client = SignerMiddleware::new(
|
||||
provider.clone(),
|
||||
wallet.wallet.clone(),
|
||||
);
|
||||
|
||||
// Create the transaction
|
||||
let tx = TransactionRequest::new()
|
||||
.to(to)
|
||||
.value(amount)
|
||||
.gas(21000);
|
||||
|
||||
// Send the transaction
|
||||
let pending_tx = client.send_transaction(tx, None)
|
||||
.await
|
||||
.map_err(|_| CryptoError::Other("Failed to send transaction".to_string()))?;
|
||||
|
||||
// Return the transaction hash instead of waiting for the receipt
|
||||
Ok(pending_tx.tx_hash())
|
||||
}
|
||||
|
||||
/// Creates a provider for the Gnosis Chain.
|
||||
pub fn create_gnosis_provider() -> Result<Provider<Http>, CryptoError> {
|
||||
Provider::<Http>::try_from(GNOSIS_RPC_URL)
|
||||
.map_err(|_| CryptoError::Other("Failed to create Gnosis provider".to_string()))
|
||||
}
|
||||
|
||||
/// Creates an Ethereum wallet from a name and the currently selected keypair.
|
||||
pub fn create_ethereum_wallet_from_name(name: &str) -> Result<EthereumWallet, CryptoError> {
|
||||
// Get the currently selected keypair
|
||||
let keypair = super::keypair::get_selected_keypair()?;
|
||||
|
||||
// Create an Ethereum wallet from the name and keypair
|
||||
let wallet = EthereumWallet::from_name_and_keypair(name, &keypair)?;
|
||||
|
||||
// Store the wallet
|
||||
let mut wallets = ETH_WALLETS.lock().unwrap();
|
||||
wallets.push(wallet.clone());
|
||||
|
||||
Ok(wallet)
|
||||
}
|
||||
|
||||
/// Creates an Ethereum wallet from a private key.
|
||||
pub fn create_ethereum_wallet_from_private_key(private_key: &str) -> Result<EthereumWallet, CryptoError> {
|
||||
// Create an Ethereum wallet from the private key
|
||||
let wallet = EthereumWallet::from_private_key(private_key)?;
|
||||
|
||||
// Store the wallet
|
||||
let mut wallets = ETH_WALLETS.lock().unwrap();
|
||||
wallets.push(wallet.clone());
|
||||
|
||||
Ok(wallet)
|
||||
}
|
@@ -3,6 +3,7 @@
|
||||
pub mod error;
|
||||
pub mod keypair;
|
||||
pub mod symmetric;
|
||||
pub mod ethereum;
|
||||
|
||||
// Re-export commonly used items for internal use
|
||||
// (Keeping this even though it's currently unused, as it's good practice for internal modules)
|
||||
|
49
src/lib.rs
49
src/lib.rs
@@ -11,6 +11,7 @@ mod tests;
|
||||
// Re-export for internal use
|
||||
use api::keypair;
|
||||
use api::symmetric;
|
||||
use api::ethereum;
|
||||
use core::error::error_to_status_code;
|
||||
|
||||
// This is like the `main` function, except for JavaScript.
|
||||
@@ -157,3 +158,51 @@ pub fn decrypt_with_password(password: &str, ciphertext: &[u8]) -> Result<Vec<u8
|
||||
symmetric::decrypt_with_password(password, ciphertext)
|
||||
.map_err(|e| JsValue::from_str(&e.to_string()))
|
||||
}
|
||||
|
||||
// --- WebAssembly Exports for Ethereum ---
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn create_ethereum_wallet() -> i32 {
|
||||
match ethereum::create_ethereum_wallet() {
|
||||
Ok(_) => 0, // Success
|
||||
Err(e) => error_to_status_code(e),
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn create_ethereum_wallet_from_name(name: &str) -> i32 {
|
||||
match ethereum::create_ethereum_wallet_from_name(name) {
|
||||
Ok(_) => 0, // Success
|
||||
Err(e) => error_to_status_code(e),
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn create_ethereum_wallet_from_private_key(private_key: &str) -> i32 {
|
||||
match ethereum::create_ethereum_wallet_from_private_key(private_key) {
|
||||
Ok(_) => 0, // Success
|
||||
Err(e) => error_to_status_code(e),
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn get_ethereum_address() -> Result<String, JsValue> {
|
||||
ethereum::get_ethereum_address()
|
||||
.map_err(|e| JsValue::from_str(&e.to_string()))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn get_ethereum_private_key() -> Result<String, JsValue> {
|
||||
ethereum::get_ethereum_private_key()
|
||||
.map_err(|e| JsValue::from_str(&e.to_string()))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn format_eth_balance(balance_hex: &str) -> String {
|
||||
ethereum::format_eth_balance(balance_hex)
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn clear_ethereum_wallets() {
|
||||
ethereum::clear_ethereum_wallets();
|
||||
}
|
||||
|
@@ -6,15 +6,16 @@ mod tests {
|
||||
|
||||
// Helper to ensure keypair is initialized for tests that need it.
|
||||
fn ensure_keypair_initialized() {
|
||||
// Use try_init which doesn't panic if already initialized
|
||||
let _ = keypair::keypair_new();
|
||||
assert!(keypair::KEYPAIR.get().is_some(), "KEYPAIR should be initialized");
|
||||
// Create a space and keypair for testing
|
||||
let _ = keypair::create_space("test_space");
|
||||
let _ = keypair::create_keypair("test_keypair");
|
||||
let _ = keypair::select_keypair("test_keypair");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keypair_generation_and_retrieval() {
|
||||
let _ = keypair::keypair_new(); // Ignore error if already initialized by another test
|
||||
let pub_key = keypair::keypair_pub_key().expect("Should be able to get pub key after init");
|
||||
ensure_keypair_initialized();
|
||||
let pub_key = keypair::pub_key().expect("Should be able to get pub key after init");
|
||||
assert!(!pub_key.is_empty(), "Public key should not be empty");
|
||||
// Basic check for SEC1 format (0x02, 0x03, or 0x04 prefix)
|
||||
assert!(pub_key.len() == 33 || pub_key.len() == 65, "Public key length is incorrect");
|
||||
@@ -25,10 +26,10 @@ mod tests {
|
||||
fn test_sign_verify_valid() {
|
||||
ensure_keypair_initialized();
|
||||
let message = b"this is a test message";
|
||||
let signature = keypair::keypair_sign(message).expect("Signing failed");
|
||||
let signature = keypair::sign(message).expect("Signing failed");
|
||||
assert!(!signature.is_empty(), "Signature should not be empty");
|
||||
|
||||
let is_valid = keypair::keypair_verify(message, &signature).expect("Verification failed");
|
||||
let is_valid = keypair::verify(message, &signature).expect("Verification failed");
|
||||
assert!(is_valid, "Signature should be valid");
|
||||
}
|
||||
|
||||
@@ -36,11 +37,11 @@ mod tests {
|
||||
fn test_verify_invalid_signature() {
|
||||
ensure_keypair_initialized();
|
||||
let message = b"another test message";
|
||||
let mut invalid_signature = keypair::keypair_sign(message).expect("Signing failed");
|
||||
let mut invalid_signature = keypair::sign(message).expect("Signing failed");
|
||||
// Tamper with the signature
|
||||
invalid_signature[0] = invalid_signature[0].wrapping_add(1);
|
||||
invalid_signature[0] = invalid_signature[0].wrapping_add(1);
|
||||
|
||||
let is_valid = keypair::keypair_verify(message, &invalid_signature).expect("Verification process failed");
|
||||
let is_valid = keypair::verify(message, &invalid_signature).expect("Verification process failed");
|
||||
assert!(!is_valid, "Tampered signature should be invalid");
|
||||
}
|
||||
|
||||
@@ -49,9 +50,14 @@ mod tests {
|
||||
ensure_keypair_initialized();
|
||||
let message = b"original message";
|
||||
let wrong_message = b"different message";
|
||||
let signature = keypair::keypair_sign(message).expect("Signing failed");
|
||||
let signature = keypair::sign(message).expect("Signing failed");
|
||||
|
||||
let is_valid = keypair::keypair_verify(wrong_message, &signature).expect("Verification process failed");
|
||||
let is_valid = keypair::verify(wrong_message, &signature).expect("Verification process failed");
|
||||
assert!(!is_valid, "Signature should be invalid for a different message");
|
||||
}
|
||||
|
||||
// Clean up after tests
|
||||
fn cleanup() {
|
||||
keypair::logout();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user