add cli with rhai scripting engine
This commit is contained in:
77
scripts/README.md
Normal file
77
scripts/README.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# WebAssembly Cryptography Module Scripts
|
||||
|
||||
This directory contains example scripts and documentation for the WebAssembly Cryptography Module's scripting and messaging capabilities.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
- `rhai/`: Example Rhai scripts that demonstrate the cryptographic operations
|
||||
- `examples/`: Documentation and code examples for messaging system integration
|
||||
|
||||
## Rhai Scripts
|
||||
|
||||
The `rhai/` directory contains example Rhai scripts that can be executed using the CLI:
|
||||
|
||||
```bash
|
||||
crypto-cli script --path scripts/rhai/example.rhai
|
||||
```
|
||||
|
||||
These scripts demonstrate how to use the cryptographic functions exposed to the Rhai scripting engine, including:
|
||||
|
||||
- Key space management
|
||||
- Keypair operations
|
||||
- Signing and verification
|
||||
- Symmetric encryption and decryption
|
||||
- Ethereum wallet operations
|
||||
|
||||
## Messaging Examples
|
||||
|
||||
The `examples/` directory contains documentation and code examples for integrating the WebAssembly Cryptography Module with messaging systems:
|
||||
|
||||
- `mycelium_example.md`: Example of using Mycelium for peer-to-peer, end-to-end encrypted messaging
|
||||
- `nats_example.md`: Example of using NATS for high-performance, client-server messaging
|
||||
|
||||
These examples demonstrate how to:
|
||||
|
||||
1. Start a listener for remote script execution
|
||||
2. Send scripts from remote systems
|
||||
3. Process the results of script execution
|
||||
4. Implement security measures for remote execution
|
||||
|
||||
## Creating Your Own Scripts
|
||||
|
||||
You can create your own Rhai scripts to automate cryptographic operations. The following functions are available in the scripting API:
|
||||
|
||||
### Key Space Management
|
||||
|
||||
- `create_key_space(name)`: Create a new key space
|
||||
- `encrypt_key_space(password)`: Encrypt the current key space
|
||||
- `decrypt_key_space(encrypted, password)`: Decrypt and load a key space
|
||||
|
||||
### Keypair Operations
|
||||
|
||||
- `create_keypair(name)`: Create a new keypair
|
||||
- `select_keypair(name)`: Select a keypair for use
|
||||
- `list_keypairs()`: List all keypairs in the current space
|
||||
|
||||
### Cryptographic Operations
|
||||
|
||||
- `sign(message)`: Sign a message with the selected keypair
|
||||
- `verify(message, signature)`: Verify a signature
|
||||
- `generate_key()`: Generate a symmetric key
|
||||
- `encrypt(key, message)`: Encrypt a message with a symmetric key
|
||||
- `decrypt(key, ciphertext)`: Decrypt a message with a symmetric key
|
||||
|
||||
### Ethereum Operations
|
||||
|
||||
- `create_ethereum_wallet()`: Create an Ethereum wallet
|
||||
- `get_ethereum_address()`: Get the Ethereum address of the current wallet
|
||||
|
||||
## Security Considerations
|
||||
|
||||
When using scripts, especially with remote execution via messaging systems, consider the following security measures:
|
||||
|
||||
1. **Script Validation**: Validate scripts before execution to prevent malicious code
|
||||
2. **Resource Limits**: Set appropriate limits on script execution to prevent denial of service
|
||||
3. **Authentication**: Ensure that only authorized users or systems can execute scripts
|
||||
4. **Sensitive Data**: Be careful about what data is returned in script results
|
||||
5. **Encryption**: Use encrypted communication channels for remote script execution
|
137
scripts/examples/mycelium_example.md
Normal file
137
scripts/examples/mycelium_example.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# Mycelium Integration Example
|
||||
|
||||
This document demonstrates how to use the Mycelium messaging system with the WebAssembly Cryptography Module for remote script execution.
|
||||
|
||||
## Overview
|
||||
|
||||
Mycelium is a peer-to-peer, end-to-end encrypted messaging system that allows for secure communication between nodes. When integrated with the WebAssembly Cryptography Module, it enables remote execution of Rhai scripts, allowing for distributed cryptographic operations.
|
||||
|
||||
## Example Scenario
|
||||
|
||||
In this example, we'll demonstrate how a remote system can send a Rhai script to the cryptographic module for execution, and receive the results.
|
||||
|
||||
### Step 1: Start the Listener
|
||||
|
||||
First, start the cryptographic module's Mycelium listener:
|
||||
|
||||
```bash
|
||||
crypto-cli listen
|
||||
```
|
||||
|
||||
This will start a Mycelium node that listens for scripts on the "crypto.scripts" topic.
|
||||
|
||||
### Step 2: Send a Script from a Remote System
|
||||
|
||||
From another system, send a Rhai script to the listener:
|
||||
|
||||
```rust
|
||||
use mycelium::{Node, Identity};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Create a Mycelium node
|
||||
let identity = Identity::random();
|
||||
let node = Node::new(identity)?;
|
||||
|
||||
// Connect to the network
|
||||
node.start().await?;
|
||||
|
||||
// Define the script to execute
|
||||
let script = r#"
|
||||
// Create a key space
|
||||
if create_key_space("remote_space") {
|
||||
print("Key space created successfully");
|
||||
|
||||
// Create a keypair
|
||||
if create_keypair("remote_keypair") {
|
||||
print("Keypair created successfully");
|
||||
|
||||
// Select the keypair
|
||||
if select_keypair("remote_keypair") {
|
||||
print("Keypair selected successfully");
|
||||
|
||||
// Sign a message
|
||||
let message = "Hello from remote system";
|
||||
let signature = sign(message);
|
||||
|
||||
print("Message: " + message);
|
||||
print("Signature: " + signature);
|
||||
|
||||
// Return the signature as the result
|
||||
signature
|
||||
} else {
|
||||
"Failed to select keypair"
|
||||
}
|
||||
} else {
|
||||
"Failed to create keypair"
|
||||
}
|
||||
} else {
|
||||
"Failed to create key space"
|
||||
}
|
||||
"#;
|
||||
|
||||
// Send the script to the crypto module
|
||||
println!("Sending script to crypto module...");
|
||||
let target_id = "RECIPIENT_ID"; // The ID of the crypto module's Mycelium node
|
||||
node.publish("crypto.scripts", target_id, script.as_bytes().to_vec()).await?;
|
||||
|
||||
// Subscribe to receive the result
|
||||
let mut receiver = node.subscribe("crypto.results").await?;
|
||||
|
||||
// Wait for the result
|
||||
println!("Waiting for result...");
|
||||
if let Some(msg) = receiver.recv().await {
|
||||
let result = String::from_utf8_lossy(&msg.payload);
|
||||
println!("Received result: {}", result);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Process the Result
|
||||
|
||||
The remote system can then process the result of the script execution:
|
||||
|
||||
```rust
|
||||
// Continue from the previous example...
|
||||
|
||||
// Parse the signature from the result
|
||||
let signature_hex = result.trim();
|
||||
|
||||
// Use the signature for further operations
|
||||
println!("Signature received: {}", signature_hex);
|
||||
|
||||
// Verify the signature locally
|
||||
let message = "Hello from remote system";
|
||||
let message_bytes = message.as_bytes();
|
||||
let signature_bytes = hex_to_bytes(signature_hex);
|
||||
|
||||
// Assuming we have the public key of the remote keypair
|
||||
let is_valid = verify_with_public_key(public_key, message_bytes, &signature_bytes);
|
||||
println!("Signature valid: {}", is_valid);
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
When using Mycelium for remote script execution, consider the following security measures:
|
||||
|
||||
1. **Authentication**: Ensure that only authorized nodes can send scripts to your crypto module.
|
||||
2. **Script Validation**: Validate scripts before execution to prevent malicious code.
|
||||
3. **Resource Limits**: Set appropriate limits on script execution to prevent denial of service.
|
||||
4. **Sensitive Data**: Be careful about what data is returned in script results.
|
||||
5. **End-to-End Encryption**: Mycelium provides end-to-end encryption, but ensure your node IDs are properly secured.
|
||||
|
||||
## Benefits of Mycelium Integration
|
||||
|
||||
- **Decentralized**: No central server required, making the system more resilient.
|
||||
- **End-to-End Encrypted**: All communication is encrypted by default.
|
||||
- **NAT Traversal**: Works across different network environments without complex configuration.
|
||||
- **Rust Native**: Seamless integration with the WebAssembly Cryptography Module.
|
||||
|
||||
## Example Use Cases
|
||||
|
||||
1. **Distributed Key Management**: Manage cryptographic keys across multiple systems.
|
||||
2. **Secure Communication**: Establish secure communication channels between systems.
|
||||
3. **Remote Signing**: Sign messages or transactions remotely without exposing private keys.
|
||||
4. **Automated Cryptographic Operations**: Schedule and execute cryptographic operations from remote systems.
|
156
scripts/examples/nats_example.md
Normal file
156
scripts/examples/nats_example.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# NATS Integration Example
|
||||
|
||||
This document demonstrates how to use the NATS messaging system with the WebAssembly Cryptography Module for remote script execution.
|
||||
|
||||
## Overview
|
||||
|
||||
NATS is a high-performance, cloud-native messaging system that provides a simple, secure, and scalable communication layer. When integrated with the WebAssembly Cryptography Module, it enables remote execution of Rhai scripts, allowing for distributed cryptographic operations.
|
||||
|
||||
## Example Scenario
|
||||
|
||||
In this example, we'll demonstrate how a remote system can send a Rhai script to the cryptographic module for execution, and receive the results.
|
||||
|
||||
### Step 1: Start the NATS Server
|
||||
|
||||
First, start a NATS server:
|
||||
|
||||
```bash
|
||||
# Install NATS server if not already installed
|
||||
# For example, on Ubuntu:
|
||||
# sudo apt-get install nats-server
|
||||
|
||||
# Start the NATS server
|
||||
nats-server
|
||||
```
|
||||
|
||||
### Step 2: Start the Listener
|
||||
|
||||
Next, start the cryptographic module's NATS listener:
|
||||
|
||||
```bash
|
||||
crypto-cli listen --server nats://localhost:4222 --subject crypto.scripts
|
||||
```
|
||||
|
||||
This will connect to the NATS server and listen for scripts on the "crypto.scripts" subject.
|
||||
|
||||
### Step 3: Send a Script from a Remote System
|
||||
|
||||
From another system, send a Rhai script to the listener:
|
||||
|
||||
```rust
|
||||
use async_nats::Client;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Connect to the NATS server
|
||||
let client = async_nats::connect("nats://localhost:4222").await?;
|
||||
|
||||
// Define the script to execute
|
||||
let script = r#"
|
||||
// Create a key space
|
||||
if create_key_space("remote_space") {
|
||||
print("Key space created successfully");
|
||||
|
||||
// Create a keypair
|
||||
if create_keypair("remote_keypair") {
|
||||
print("Keypair created successfully");
|
||||
|
||||
// Select the keypair
|
||||
if select_keypair("remote_keypair") {
|
||||
print("Keypair selected successfully");
|
||||
|
||||
// Sign a message
|
||||
let message = "Hello from remote system";
|
||||
let signature = sign(message);
|
||||
|
||||
print("Message: " + message);
|
||||
print("Signature: " + signature);
|
||||
|
||||
// Return the signature as the result
|
||||
signature
|
||||
} else {
|
||||
"Failed to select keypair"
|
||||
}
|
||||
} else {
|
||||
"Failed to create keypair"
|
||||
}
|
||||
} else {
|
||||
"Failed to create key space"
|
||||
}
|
||||
"#;
|
||||
|
||||
// Send the script to the crypto module with a reply subject
|
||||
println!("Sending script to crypto module...");
|
||||
let reply = client.request("crypto.scripts", script.into()).await?;
|
||||
|
||||
// Process the reply
|
||||
let result = String::from_utf8_lossy(&reply.payload);
|
||||
println!("Received result: {}", result);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: Process the Result
|
||||
|
||||
The remote system can then process the result of the script execution:
|
||||
|
||||
```rust
|
||||
// Continue from the previous example...
|
||||
|
||||
// Parse the signature from the result
|
||||
let signature_hex = result.trim();
|
||||
|
||||
// Use the signature for further operations
|
||||
println!("Signature received: {}", signature_hex);
|
||||
|
||||
// Verify the signature locally
|
||||
let message = "Hello from remote system";
|
||||
let message_bytes = message.as_bytes();
|
||||
let signature_bytes = hex_to_bytes(signature_hex);
|
||||
|
||||
// Assuming we have the public key of the remote keypair
|
||||
let is_valid = verify_with_public_key(public_key, message_bytes, &signature_bytes);
|
||||
println!("Signature valid: {}", is_valid);
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
When using NATS for remote script execution, consider the following security measures:
|
||||
|
||||
1. **TLS**: Configure NATS to use TLS for secure communication.
|
||||
2. **Authentication**: Set up user authentication for the NATS server.
|
||||
3. **Authorization**: Configure permissions to control which clients can publish/subscribe to which subjects.
|
||||
4. **Script Validation**: Validate scripts before execution to prevent malicious code.
|
||||
5. **Resource Limits**: Set appropriate limits on script execution to prevent denial of service.
|
||||
6. **Sensitive Data**: Be careful about what data is returned in script results.
|
||||
|
||||
## Benefits of NATS Integration
|
||||
|
||||
- **High Performance**: NATS is designed for high throughput and low latency.
|
||||
- **Scalability**: NATS can scale to handle millions of messages per second.
|
||||
- **Mature Ecosystem**: NATS has a mature ecosystem with clients for many languages.
|
||||
- **Flexible Deployment**: NATS can be deployed in various configurations, from a single server to a distributed cluster.
|
||||
- **Quality of Service**: NATS supports different quality of service levels, including at-most-once, at-least-once, and exactly-once delivery.
|
||||
|
||||
## Example Use Cases
|
||||
|
||||
1. **Centralized Key Management**: Manage cryptographic keys from a central service.
|
||||
2. **Secure API**: Provide a secure API for cryptographic operations.
|
||||
3. **Remote Signing Service**: Offer signing as a service without exposing private keys.
|
||||
4. **Automated Cryptographic Operations**: Schedule and execute cryptographic operations from remote systems.
|
||||
|
||||
## Comparison with Mycelium
|
||||
|
||||
| Feature | NATS | Mycelium |
|
||||
|---------|------|----------|
|
||||
| Architecture | Client-server | Peer-to-peer |
|
||||
| Deployment | Requires server setup | No central server needed |
|
||||
| Security | TLS, authentication, authorization | End-to-end encryption by default |
|
||||
| Performance | Optimized for high throughput | Good for P2P scenarios |
|
||||
| Maturity | Established project | Newer project |
|
||||
| Documentation | Extensive | Limited |
|
||||
| Language Support | Multiple language clients | Rust native |
|
||||
| NAT Traversal | Requires configuration | Built-in |
|
||||
|
||||
Choose NATS if you prefer a centralized, high-performance messaging system with extensive documentation and language support. Choose Mycelium if you prefer a decentralized, peer-to-peer approach with built-in end-to-end encryption and NAT traversal.
|
57
scripts/rhai/README.md
Normal file
57
scripts/rhai/README.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Rhai Scripting for WebAssembly Cryptography Module
|
||||
|
||||
This directory contains example Rhai scripts that demonstrate how to use the WebAssembly Cryptography Module's scripting capabilities.
|
||||
|
||||
## Key Space Persistence
|
||||
|
||||
|
||||
The Rhai API now supports key space persistence, allowing you to create key spaces and keypairs in one script and use them in another. This is achieved through the following functions:
|
||||
|
||||
### Key Space Management Functions
|
||||
|
||||
- `load_key_space(name, password)`: Loads a key space from disk by name and decrypts it with the provided password.
|
||||
- `create_key_space(name, password)`: Creates a new key space with the given name and automatically saves it to disk encrypted with the provided password.
|
||||
- `encrypt_key_space(password)`: Encrypts the current key space and returns the encrypted data as a string.
|
||||
- `decrypt_key_space(encrypted_data, password)`: Decrypts an encrypted key space and sets it as the current key space.
|
||||
|
||||
### Example Usage
|
||||
|
||||
```rhai
|
||||
// Create a key space (automatically saves to disk)
|
||||
let space_name = "my_space";
|
||||
let password = "secure_password";
|
||||
|
||||
if create_key_space(space_name, password) {
|
||||
// Create keypairs (automatically saves to disk)
|
||||
create_keypair("my_keypair", password);
|
||||
}
|
||||
|
||||
// Later, in another script:
|
||||
if load_key_space(space_name, password) {
|
||||
// Use the keypair
|
||||
select_keypair("my_keypair");
|
||||
let signature = sign("Hello, world!");
|
||||
}
|
||||
```
|
||||
|
||||
## Example Scripts
|
||||
|
||||
1. **example.rhai**: Basic example demonstrating key management, signing, and encryption.
|
||||
2. **advanced_example.rhai**: Advanced example with error handling and more complex operations.
|
||||
3. **key_persistence_example.rhai**: Demonstrates creating and saving a key space to disk.
|
||||
4. **load_existing_space.rhai**: Shows how to load a previously created key space and use its keypairs.
|
||||
|
||||
## Key Space Storage
|
||||
|
||||
Key spaces are stored in the `~/.crypto-cli/key-spaces/` directory by default. Each key space is stored in a separate JSON file named after the key space (e.g., `my_space.json`).
|
||||
|
||||
## Security
|
||||
|
||||
Key spaces are encrypted with ChaCha20Poly1305 using a key derived from the provided password. The encryption ensures that the key material is secure at rest.
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use Strong Passwords**: Since the security of your key spaces depends on the strength of your passwords, use strong, unique passwords.
|
||||
2. **Backup Key Spaces**: Regularly backup your key spaces directory to prevent data loss.
|
||||
3. **Script Organization**: Split your scripts into logical units, with separate scripts for key creation and key usage.
|
||||
4. **Error Handling**: Always check the return values of functions to ensure operations succeeded before proceeding.
|
233
scripts/rhai/advanced_example.rhai
Normal file
233
scripts/rhai/advanced_example.rhai
Normal file
@@ -0,0 +1,233 @@
|
||||
// Advanced Rhai script example for WebAssembly Cryptography Module
|
||||
// This script demonstrates conditional logic, error handling, and more complex operations
|
||||
|
||||
// Function to create a key space with error handling
|
||||
fn setup_key_space(name, password) {
|
||||
print("Attempting: Create key space: " + name);
|
||||
let result = create_key_space(name, password);
|
||||
|
||||
if result {
|
||||
print("✅ Create key space succeeded!");
|
||||
return true;
|
||||
} else {
|
||||
print("❌ Create key space failed!");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Function to create and select a keypair
|
||||
fn setup_keypair(name, password) {
|
||||
print("Attempting: Create keypair: " + name);
|
||||
let result = create_keypair(name, password);
|
||||
|
||||
if result {
|
||||
print("✅ Create keypair succeeded!");
|
||||
|
||||
print("Attempting: Select keypair: " + name);
|
||||
let selected = select_keypair(name);
|
||||
|
||||
if selected {
|
||||
print("✅ Select keypair succeeded!");
|
||||
return true;
|
||||
} else {
|
||||
print("❌ Select keypair failed!");
|
||||
}
|
||||
} else {
|
||||
print("❌ Create keypair failed!");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Function to sign multiple messages
|
||||
fn sign_messages(messages) {
|
||||
let signatures = [];
|
||||
|
||||
for message in messages {
|
||||
print("Signing message: " + message);
|
||||
print("Attempting: Sign message");
|
||||
let signature = sign(message);
|
||||
|
||||
if signature != "" {
|
||||
print("✅ Sign message succeeded!");
|
||||
signatures.push(#{
|
||||
message: message,
|
||||
signature: signature
|
||||
});
|
||||
} else {
|
||||
print("❌ Sign message failed!");
|
||||
}
|
||||
}
|
||||
|
||||
return signatures;
|
||||
}
|
||||
|
||||
// Function to verify signatures
|
||||
fn verify_signatures(signed_messages) {
|
||||
let results = [];
|
||||
|
||||
for item in signed_messages {
|
||||
let message = item.message;
|
||||
let signature = item.signature;
|
||||
|
||||
print("Verifying signature for: " + message);
|
||||
print("Attempting: Verify signature");
|
||||
let is_valid = verify(message, signature);
|
||||
|
||||
if is_valid {
|
||||
print("✅ Verify signature succeeded!");
|
||||
} else {
|
||||
print("❌ Verify signature failed!");
|
||||
}
|
||||
|
||||
results.push(#{
|
||||
message: message,
|
||||
valid: is_valid
|
||||
});
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
// Function to encrypt multiple messages
|
||||
fn encrypt_messages(messages) {
|
||||
// Generate a symmetric key
|
||||
print("Attempting: Generate symmetric key");
|
||||
let key = generate_key();
|
||||
|
||||
if key == "" {
|
||||
print("❌ Generate symmetric key failed!");
|
||||
return [];
|
||||
}
|
||||
|
||||
print("✅ Generate symmetric key succeeded!");
|
||||
print("Using key: " + key);
|
||||
let encrypted_messages = [];
|
||||
|
||||
for message in messages {
|
||||
print("Encrypting message: " + message);
|
||||
print("Attempting: Encrypt message");
|
||||
let encrypted = encrypt(key, message);
|
||||
|
||||
if encrypted != "" {
|
||||
print("✅ Encrypt message succeeded!");
|
||||
encrypted_messages.push(#{
|
||||
original: message,
|
||||
encrypted: encrypted,
|
||||
key: key
|
||||
});
|
||||
} else {
|
||||
print("❌ Encrypt message failed!");
|
||||
}
|
||||
}
|
||||
|
||||
return encrypted_messages;
|
||||
}
|
||||
|
||||
// Function to decrypt messages
|
||||
fn decrypt_messages(encrypted_messages) {
|
||||
let decrypted_messages = [];
|
||||
|
||||
for item in encrypted_messages {
|
||||
let encrypted = item.encrypted;
|
||||
let key = item.key;
|
||||
let original = item.original;
|
||||
|
||||
print("Decrypting message...");
|
||||
print("Attempting: Decrypt message");
|
||||
let decrypted = decrypt(key, encrypted);
|
||||
|
||||
if decrypted != false {
|
||||
let success = decrypted == original;
|
||||
|
||||
decrypted_messages.push(#{
|
||||
decrypted: decrypted,
|
||||
original: original,
|
||||
success: success
|
||||
});
|
||||
|
||||
if success {
|
||||
print("Decryption matched original ✅");
|
||||
} else {
|
||||
print("Decryption did not match original ❌");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return decrypted_messages;
|
||||
}
|
||||
|
||||
// Main script execution
|
||||
print("=== Advanced Cryptography Script ===");
|
||||
|
||||
// Set up key space
|
||||
let space_name = "advanced_space";
|
||||
let password = "secure_password123";
|
||||
|
||||
if setup_key_space(space_name, password) {
|
||||
print("\n--- Key space setup complete ---\n");
|
||||
|
||||
// Set up keypair
|
||||
if setup_keypair("advanced_keypair", password) {
|
||||
print("\n--- Keypair setup complete ---\n");
|
||||
|
||||
// Define messages to sign
|
||||
let messages = [
|
||||
"This is the first message to sign",
|
||||
"Here's another message that needs signing",
|
||||
"And a third message for good measure"
|
||||
];
|
||||
|
||||
// Sign messages
|
||||
print("\n--- Signing Messages ---\n");
|
||||
let signed_messages = sign_messages(messages);
|
||||
|
||||
// Verify signatures
|
||||
print("\n--- Verifying Signatures ---\n");
|
||||
let verification_results = verify_signatures(signed_messages);
|
||||
|
||||
// Count successful verifications
|
||||
let successful_verifications = verification_results.filter(|r| r.valid).len();
|
||||
print("Successfully verified " + successful_verifications + " out of " + verification_results.len() + " signatures");
|
||||
|
||||
// Encrypt messages
|
||||
print("\n--- Encrypting Messages ---\n");
|
||||
let encrypted_messages = encrypt_messages(messages);
|
||||
|
||||
// Decrypt messages
|
||||
print("\n--- Decrypting Messages ---\n");
|
||||
let decryption_results = decrypt_messages(encrypted_messages);
|
||||
|
||||
// Count successful decryptions
|
||||
let successful_decryptions = decryption_results.filter(|r| r.success).len();
|
||||
print("Successfully decrypted " + successful_decryptions + " out of " + decryption_results.len() + " messages");
|
||||
|
||||
// Create Ethereum wallet
|
||||
print("\n--- Creating Ethereum Wallet ---\n");
|
||||
print("Attempting: Create Ethereum wallet");
|
||||
let wallet_created = create_ethereum_wallet();
|
||||
|
||||
if wallet_created {
|
||||
print("✅ Create Ethereum wallet succeeded!");
|
||||
|
||||
print("Attempting: Get Ethereum address");
|
||||
let address = get_ethereum_address();
|
||||
|
||||
if address != "" {
|
||||
print("✅ Get Ethereum address succeeded!");
|
||||
print("Ethereum wallet address: " + address);
|
||||
} else {
|
||||
print("❌ Get Ethereum address failed!");
|
||||
}
|
||||
} else {
|
||||
print("❌ Create Ethereum wallet failed!");
|
||||
}
|
||||
|
||||
print("\n=== Script execution completed successfully! ===");
|
||||
} else {
|
||||
print("Failed to set up keypair. Aborting script.");
|
||||
}
|
||||
} else {
|
||||
print("Failed to set up key space. Aborting script.");
|
||||
}
|
85
scripts/rhai/example.rhai
Normal file
85
scripts/rhai/example.rhai
Normal file
@@ -0,0 +1,85 @@
|
||||
// Example Rhai script for WebAssembly Cryptography Module
|
||||
// This script demonstrates key management, signing, and encryption
|
||||
|
||||
// Step 1: Create and manage a key space
|
||||
let space_name = "demo_space";
|
||||
let password = "secure_password123";
|
||||
|
||||
print("Creating key space: " + space_name);
|
||||
if create_key_space(space_name, password) {
|
||||
print("✓ Key space created successfully");
|
||||
|
||||
// Step 2: Create and use keypairs
|
||||
print("\nCreating keypairs...");
|
||||
if create_keypair("signing_key", password) {
|
||||
print("✓ Created signing keypair");
|
||||
}
|
||||
|
||||
if create_keypair("encryption_key", password) {
|
||||
print("✓ Created encryption keypair");
|
||||
}
|
||||
|
||||
// List all keypairs
|
||||
let keypairs = list_keypairs();
|
||||
print("Available keypairs: " + keypairs);
|
||||
|
||||
// Step 3: Sign a message
|
||||
print("\nPerforming signing operations...");
|
||||
if select_keypair("signing_key") {
|
||||
print("✓ Selected signing keypair");
|
||||
|
||||
let message = "This is a secure message that needs to be signed";
|
||||
print("Message: " + message);
|
||||
|
||||
let signature = sign(message);
|
||||
print("Signature: " + signature);
|
||||
|
||||
// Verify the signature
|
||||
let is_valid = verify(message, signature);
|
||||
if is_valid {
|
||||
print("Signature verification: ✓ Valid");
|
||||
} else {
|
||||
print("Signature verification: ✗ Invalid");
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Encrypt and decrypt data
|
||||
print("\nPerforming encryption operations...");
|
||||
|
||||
// Generate a symmetric key
|
||||
let sym_key = generate_key();
|
||||
print("Generated symmetric key: " + sym_key);
|
||||
|
||||
// Encrypt a message
|
||||
let secret = "This is a top secret message that must be encrypted";
|
||||
print("Original message: " + secret);
|
||||
|
||||
let encrypted_data = encrypt(sym_key, secret);
|
||||
print("Encrypted data: " + encrypted_data);
|
||||
|
||||
// Decrypt the message
|
||||
let decrypted_data = decrypt(sym_key, encrypted_data);
|
||||
print("Decrypted message: " + decrypted_data);
|
||||
|
||||
// Verify decryption was successful
|
||||
if decrypted_data == secret {
|
||||
print("✓ Encryption/decryption successful");
|
||||
} else {
|
||||
print("✗ Encryption/decryption failed");
|
||||
}
|
||||
|
||||
// Step 5: Create an Ethereum wallet
|
||||
print("\nCreating Ethereum wallet...");
|
||||
if select_keypair("encryption_key") {
|
||||
print("✓ Selected keypair for Ethereum wallet");
|
||||
|
||||
if create_ethereum_wallet() {
|
||||
print("✓ Ethereum wallet created");
|
||||
|
||||
let address = get_ethereum_address();
|
||||
print("Ethereum address: " + address);
|
||||
}
|
||||
}
|
||||
|
||||
print("\nScript execution completed successfully!");
|
||||
}
|
65
scripts/rhai/key_persistence_example.rhai
Normal file
65
scripts/rhai/key_persistence_example.rhai
Normal file
@@ -0,0 +1,65 @@
|
||||
// Example Rhai script demonstrating key space persistence
|
||||
// This script shows how to create, save, and load key spaces
|
||||
|
||||
// Step 1: Create a key space
|
||||
let space_name = "persistent_space";
|
||||
let password = "secure_password123";
|
||||
|
||||
print("Creating key space: " + space_name);
|
||||
if create_key_space(space_name, password) {
|
||||
print("✓ Key space created successfully");
|
||||
|
||||
// Step 2: Create keypairs in this space
|
||||
print("\nCreating keypairs...");
|
||||
if create_keypair("persistent_key1", password) {
|
||||
print("✓ Created first keypair");
|
||||
}
|
||||
|
||||
if create_keypair("persistent_key2", password) {
|
||||
print("✓ Created second keypair");
|
||||
}
|
||||
|
||||
// List all keypairs
|
||||
let keypairs = list_keypairs();
|
||||
print("Available keypairs: " + keypairs);
|
||||
|
||||
// Step 3: Clear the session (simulate closing and reopening the CLI)
|
||||
print("\nClearing session (simulating restart)...");
|
||||
// Note: In a real script, you would exit here and run a new script
|
||||
// For demonstration purposes, we'll continue in the same script
|
||||
|
||||
// Step 4: Load the key space from disk
|
||||
print("\nLoading key space from disk...");
|
||||
if load_key_space(space_name, password) {
|
||||
print("✓ Key space loaded successfully");
|
||||
|
||||
// Verify the keypairs are still available
|
||||
let loaded_keypairs = list_keypairs();
|
||||
print("Keypairs after loading: " + loaded_keypairs);
|
||||
|
||||
// Step 5: Use a keypair from the loaded space
|
||||
print("\nSelecting and using a keypair...");
|
||||
if select_keypair("persistent_key1") {
|
||||
print("✓ Selected keypair");
|
||||
|
||||
let message = "This message was signed using a keypair from a loaded key space";
|
||||
let signature = sign(message);
|
||||
print("Message: " + message);
|
||||
print("Signature: " + signature);
|
||||
|
||||
// Verify the signature
|
||||
let is_valid = verify(message, signature);
|
||||
if is_valid {
|
||||
print("Signature verification: ✓ Valid");
|
||||
} else {
|
||||
print("Signature verification: ✗ Invalid");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print("✗ Failed to load key space");
|
||||
}
|
||||
} else {
|
||||
print("✗ Failed to create key space");
|
||||
}
|
||||
|
||||
print("\nScript execution completed!");
|
65
scripts/rhai/load_existing_space.rhai
Normal file
65
scripts/rhai/load_existing_space.rhai
Normal file
@@ -0,0 +1,65 @@
|
||||
// Example Rhai script demonstrating loading an existing key space
|
||||
// This script shows how to load a previously created key space and use its keypairs
|
||||
|
||||
// Define the key space name and password
|
||||
let space_name = "persistent_space";
|
||||
let password = "secure_password123";
|
||||
|
||||
print("Loading existing key space: " + space_name);
|
||||
|
||||
// Load the key space from disk
|
||||
if load_key_space(space_name, password) {
|
||||
print("✓ Key space loaded successfully");
|
||||
|
||||
// List available keypairs
|
||||
let keypairs = list_keypairs();
|
||||
print("Available keypairs: " + keypairs);
|
||||
|
||||
// Use both keypairs to sign different messages
|
||||
if select_keypair("persistent_key1") {
|
||||
print("\nUsing persistent_key1:");
|
||||
let message1 = "Message signed with the first keypair";
|
||||
let signature1 = sign(message1);
|
||||
print("Message: " + message1);
|
||||
print("Signature: " + signature1);
|
||||
|
||||
let is_valid1 = verify(message1, signature1);
|
||||
if is_valid1 {
|
||||
print("Verification: ✓ Valid");
|
||||
} else {
|
||||
print("Verification: ✗ Invalid");
|
||||
}
|
||||
}
|
||||
|
||||
if select_keypair("persistent_key2") {
|
||||
print("\nUsing persistent_key2:");
|
||||
let message2 = "Message signed with the second keypair";
|
||||
let signature2 = sign(message2);
|
||||
print("Message: " + message2);
|
||||
print("Signature: " + signature2);
|
||||
|
||||
let is_valid2 = verify(message2, signature2);
|
||||
if is_valid2 {
|
||||
print("Verification: ✓ Valid");
|
||||
} else {
|
||||
print("Verification: ✗ Invalid");
|
||||
}
|
||||
}
|
||||
|
||||
// Create an Ethereum wallet using one of the keypairs
|
||||
print("\nCreating Ethereum wallet from persistent keypair:");
|
||||
if select_keypair("persistent_key1") {
|
||||
if create_ethereum_wallet() {
|
||||
print("✓ Ethereum wallet created");
|
||||
|
||||
let address = get_ethereum_address();
|
||||
print("Ethereum address: " + address);
|
||||
} else {
|
||||
print("✗ Failed to create Ethereum wallet");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print("✗ Failed to load key space. Make sure you've run key_persistence_example.rhai first.");
|
||||
}
|
||||
|
||||
print("\nScript execution completed!");
|
103
scripts/run_examples.sh
Executable file
103
scripts/run_examples.sh
Executable file
@@ -0,0 +1,103 @@
|
||||
#!/bin/bash
|
||||
# Script to run the example Rhai scripts and demonstrate the WebAssembly Cryptography Module
|
||||
|
||||
# Colors for output
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to print section headers
|
||||
print_header() {
|
||||
echo -e "\n${BLUE}======================================${NC}"
|
||||
echo -e "${BLUE}$1${NC}"
|
||||
echo -e "${BLUE}======================================${NC}\n"
|
||||
}
|
||||
|
||||
# Function to run a Rhai script
|
||||
run_script() {
|
||||
echo -e "${YELLOW}Running script: $1${NC}"
|
||||
echo -e "${YELLOW}------------------------${NC}"
|
||||
|
||||
if [ -f "$1" ]; then
|
||||
echo -e "${GREEN}Script output:${NC}"
|
||||
crypto-cli script "$1"
|
||||
echo -e "\n${GREEN}Script execution completed.${NC}"
|
||||
else
|
||||
echo -e "${RED}Error: Script file not found: $1${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if crypto-cli is installed
|
||||
if ! command -v crypto-cli &> /dev/null; then
|
||||
echo -e "${RED}Error: crypto-cli is not installed or not in PATH.${NC}"
|
||||
echo -e "${YELLOW}Please build and install the CLI first:${NC}"
|
||||
echo -e " cargo build --bin crypto-cli"
|
||||
echo -e " cargo install --path ."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Print welcome message
|
||||
print_header "WebAssembly Cryptography Module Examples"
|
||||
echo -e "This script will run the example Rhai scripts to demonstrate the functionality of the WebAssembly Cryptography Module."
|
||||
echo -e "Make sure you have built and installed the CLI before running this script.\n"
|
||||
|
||||
# Ask user which example to run
|
||||
echo -e "${YELLOW}Which example would you like to run?${NC}"
|
||||
echo -e "1. Basic example (key management, signing, encryption)"
|
||||
echo -e "2. Advanced example (error handling, multiple operations)"
|
||||
echo -e "3. Multi-script workflows (chaining scripts)"
|
||||
echo -e "4. Run all examples"
|
||||
echo -e "5. Exit"
|
||||
|
||||
read -p "Enter your choice (1-4): " choice
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
print_header "Running Basic Example"
|
||||
run_script "scripts/rhai/example.rhai"
|
||||
;;
|
||||
2)
|
||||
print_header "Running Advanced Example"
|
||||
run_script "scripts/rhai/advanced_example.rhai"
|
||||
;;
|
||||
3)
|
||||
print_header "Running Multi-Script Workflows"
|
||||
run_script "scripts/rhai/key_persistence_example.rhai"
|
||||
echo -e "\n"
|
||||
run_script "scripts/rhai/load_existing_space.rhai"
|
||||
;;
|
||||
4)
|
||||
print_header "Running All Examples"
|
||||
run_script "scripts/rhai/example.rhai"
|
||||
echo -e "\n"
|
||||
run_script "scripts/rhai/advanced_example.rhai"
|
||||
echo -e "\n"
|
||||
run_script "scripts/rhai/key_persistence_example.rhai"
|
||||
echo -e "\n"
|
||||
run_script "scripts/rhai/load_existing_space.rhai"
|
||||
;;
|
||||
5)
|
||||
echo -e "${YELLOW}Exiting...${NC}"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Invalid choice. Exiting...${NC}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Print information about messaging examples
|
||||
print_header "Messaging System Examples"
|
||||
echo -e "To try the messaging system examples, you can:"
|
||||
echo -e "1. Start a listener for remote script execution:"
|
||||
echo -e " ${YELLOW}crypto-cli listen${NC}"
|
||||
echo -e ""
|
||||
echo -e "2. For Mycelium integration, see:"
|
||||
echo -e " ${YELLOW}scripts/examples/mycelium_example.md${NC}"
|
||||
echo -e ""
|
||||
echo -e "3. For NATS integration, see:"
|
||||
echo -e " ${YELLOW}scripts/examples/nats_example.md${NC}"
|
||||
|
||||
echo -e "\n${GREEN}Thank you for trying the WebAssembly Cryptography Module examples!${NC}"
|
Reference in New Issue
Block a user