webassembly/scripts/examples/nats_example.md

5.7 KiB

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:

# 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:

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:

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:

// 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.