Rust Platform Guide
This guide covers the installation, setup, and usage of MetaMUI Crypto Primitives in Rust projects.
Installation
Add MetaMUI to your Cargo.toml:
[dependencies]
metamui-crypto = "0.1.0"
Or install specific algorithms:
[dependencies]
metamui-crypto-aes = "0.1.0"
metamui-crypto-chacha20 = "0.1.0"
metamui-crypto-ed25519 = "0.1.0"
Quick Start
use metamui_crypto::{Ed25519, ChaCha20Poly1305};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Generate Ed25519 keypair
let keypair = Ed25519::generate_keypair();
// Sign a message
let message = b"Hello, MetaMUI!";
let signature = Ed25519::sign(message, &keypair.private_key)?;
// Verify signature
let is_valid = Ed25519::verify(&signature, message, &keypair.public_key)?;
println!("Signature valid: {}", is_valid);
// Encrypt with ChaCha20-Poly1305
let key = ChaCha20Poly1305::generate_key();
let cipher = ChaCha20Poly1305::new(&key);
let plaintext = b"Secret message";
let nonce = ChaCha20Poly1305::generate_nonce();
let (ciphertext, tag) = cipher.encrypt(plaintext, &nonce, None)?;
// Decrypt
let decrypted = cipher.decrypt(&ciphertext, &tag, &nonce, None)?;
assert_eq!(decrypted, plaintext);
Ok(())
}
Features
Feature Flags
Enable specific features in Cargo.toml:
[dependencies]
metamui-crypto = { version = "0.1.0", features = ["full"] }
# Or select specific features:
metamui-crypto = {
version = "0.1.0",
features = ["aes", "chacha20", "ed25519", "post-quantum"]
}
Available features:
full- All algorithmspost-quantum- ML-KEM, Dilithium, Falcon, NTRUsignatures- Ed25519, Sr25519symmetric- AES, ChaCha20, ARIA, Camelliahashing- SHA2, SHA3, Blake2, Blake3kdf- Argon2, PBKDF2, HKDFno-std- No standard library supportzeroize- Secure memory clearing
No-std Support
For embedded systems:
[dependencies]
metamui-crypto = { version = "0.1.0", default-features = false, features = ["no-std"] }
#![no_std]
use metamui_crypto::{ChaCha20, Poly1305};
// Works in no-std environments
Common Patterns
Error Handling
use metamui_crypto::{Error, Result};
fn encrypt_data(data: &[u8], key: &[u8]) -> Result<Vec<u8>> {
if key.len() != 32 {
return Err(Error::InvalidKeyLength);
}
let cipher = ChaCha20Poly1305::new(key)?;
let nonce = ChaCha20Poly1305::generate_nonce();
let (ciphertext, tag) = cipher.encrypt(data, &nonce, None)?;
// Combine nonce + tag + ciphertext
let mut result = Vec::with_capacity(12 + 16 + ciphertext.len());
result.extend_from_slice(&nonce);
result.extend_from_slice(&tag);
result.extend_from_slice(&ciphertext);
Ok(result)
}
Secure Key Management
use metamui_crypto::{SecureBytes, Zeroize};
use std::ops::Drop;
struct SecretKey {
key: SecureBytes<32>,
}
impl SecretKey {
fn new() -> Self {
Self {
key: SecureBytes::random(),
}
}
fn as_bytes(&self) -> &[u8] {
self.key.as_ref()
}
}
impl Drop for SecretKey {
fn drop(&mut self) {
self.key.zeroize();
}
}
Async Support
use metamui_crypto::{Argon2, ChaCha20Poly1305};
use tokio::task;
async fn derive_and_encrypt(password: String, data: Vec<u8>) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
// CPU-intensive key derivation in blocking task
let key = task::spawn_blocking(move || {
let salt = generate_salt();
Argon2::default().derive_key(password.as_bytes(), &salt, 32)
}).await??;
// Encryption can be done in async context
let cipher = ChaCha20Poly1305::new(&key);
let nonce = ChaCha20Poly1305::generate_nonce();
let (ciphertext, tag) = cipher.encrypt(&data, &nonce, None)?;
Ok(ciphertext)
}
Performance Optimization
Hardware Acceleration
use metamui_crypto::aes::{Aes256, HardwareAcceleration};
fn setup_aes() -> Aes256 {
if HardwareAcceleration::available() {
println!("Using AES-NI hardware acceleration");
Aes256::with_hardware_acceleration()
} else {
println!("Using software AES implementation");
Aes256::new()
}
}
Batch Operations
use metamui_crypto::Ed25519;
use rayon::prelude::*;
fn verify_signatures_parallel(
signatures: &[(Signature, Message, PublicKey)]
) -> Vec<bool> {
signatures
.par_iter()
.map(|(sig, msg, pk)| Ed25519::verify(sig, msg, pk).unwrap_or(false))
.collect()
}
// Or use built-in batch verification (more efficient)
fn verify_signatures_batch(
signatures: &[Signature],
messages: &[Message],
public_keys: &[PublicKey],
) -> Result<bool, Error> {
Ed25519::batch_verify(signatures, messages, public_keys)
}
Testing
Unit Tests
#[cfg(test)]
mod tests {
use super::*;
use metamui_crypto::test_vectors;
#[test]
fn test_encryption_roundtrip() {
let key = ChaCha20Poly1305::generate_key();
let cipher = ChaCha20Poly1305::new(&key);
let plaintext = b"test message";
let nonce = ChaCha20Poly1305::generate_nonce();
let (ciphertext, tag) = cipher.encrypt(plaintext, &nonce, None).unwrap();
let decrypted = cipher.decrypt(&ciphertext, &tag, &nonce, None).unwrap();
assert_eq!(decrypted, plaintext);
}
#[test]
fn test_known_vectors() {
for vector in test_vectors::chacha20_poly1305() {
let cipher = ChaCha20Poly1305::new(&vector.key);
let (ciphertext, tag) = cipher.encrypt(
&vector.plaintext,
&vector.nonce,
vector.aad.as_deref()
).unwrap();
assert_eq!(ciphertext, vector.expected_ciphertext);
assert_eq!(tag, vector.expected_tag);
}
}
}
Benchmarking
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use metamui_crypto::{ChaCha20Poly1305, Aes256Gcm};
fn benchmark_encryption(c: &mut Criterion) {
let key = [0u8; 32];
let nonce = [0u8; 12];
let data = vec![0u8; 1024 * 1024]; // 1MB
let mut group = c.benchmark_group("encryption");
group.bench_function("chacha20-poly1305", |b| {
let cipher = ChaCha20Poly1305::new(&key);
b.iter(|| {
let (ct, tag) = cipher.encrypt(black_box(&data), &nonce, None).unwrap();
black_box((ct, tag));
});
});
group.bench_function("aes256-gcm", |b| {
let cipher = Aes256Gcm::new(&key);
b.iter(|| {
let (ct, tag) = cipher.encrypt(black_box(&data), &nonce, None).unwrap();
black_box((ct, tag));
});
});
group.finish();
}
criterion_group!(benches, benchmark_encryption);
criterion_main!(benches);
Integration Examples
Web Server (Actix-web)
use actix_web::{web, App, HttpServer, Result};
use metamui_crypto::{Ed25519, ChaCha20Poly1305};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct EncryptRequest {
data: String,
}
#[derive(Serialize)]
struct EncryptResponse {
ciphertext: String,
nonce: String,
tag: String,
}
async fn encrypt_endpoint(
req: web::Json<EncryptRequest>,
key: web::Data<[u8; 32]>,
) -> Result<web::Json<EncryptResponse>> {
let cipher = ChaCha20Poly1305::new(&**key);
let nonce = ChaCha20Poly1305::generate_nonce();
let (ciphertext, tag) = cipher
.encrypt(req.data.as_bytes(), &nonce, None)
.map_err(|e| actix_web::error::ErrorInternalServerError(e))?;
Ok(web::Json(EncryptResponse {
ciphertext: base64::encode(&ciphertext),
nonce: base64::encode(&nonce),
tag: base64::encode(&tag),
}))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let key = ChaCha20Poly1305::generate_key();
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(key))
.route("/encrypt", web::post().to(encrypt_endpoint))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
CLI Tool
use clap::{Parser, Subcommand};
use metamui_crypto::{Ed25519, ChaCha20Poly1305};
use std::fs;
use std::path::PathBuf;
#[derive(Parser)]
#[command(name = "metamui-crypto")]
#[command(about = "MetaMUI Crypto CLI", long_about = None)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// Generate a new keypair
Keygen {
/// Algorithm to use
#[arg(short, long, default_value = "ed25519")]
algorithm: String,
/// Output file
#[arg(short, long)]
output: PathBuf,
},
/// Encrypt a file
Encrypt {
/// Input file
#[arg(short, long)]
input: PathBuf,
/// Output file
#[arg(short, long)]
output: PathBuf,
/// Key file
#[arg(short, long)]
key: PathBuf,
},
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let cli = Cli::parse();
match cli.command {
Commands::Keygen { algorithm, output } => {
match algorithm.as_str() {
"ed25519" => {
let keypair = Ed25519::generate_keypair();
let encoded = serde_json::to_string_pretty(&keypair)?;
fs::write(output, encoded)?;
println!("Keypair generated successfully");
}
_ => eprintln!("Unknown algorithm: {}", algorithm),
}
}
Commands::Encrypt { input, output, key } => {
let key_data = fs::read(key)?;
let key: [u8; 32] = key_data.try_into()
.map_err(|_| "Invalid key length")?;
let plaintext = fs::read(input)?;
let cipher = ChaCha20Poly1305::new(&key);
let nonce = ChaCha20Poly1305::generate_nonce();
let (ciphertext, tag) = cipher.encrypt(&plaintext, &nonce, None)?;
// Write nonce + tag + ciphertext
let mut output_data = Vec::new();
output_data.extend_from_slice(&nonce);
output_data.extend_from_slice(&tag);
output_data.extend_from_slice(&ciphertext);
fs::write(output, output_data)?;
println!("File encrypted successfully");
}
}
Ok(())
}
Best Practices
- Always use
zeroizefor sensitive data - Generate random values using
OsRngorThreadRng - Use type-safe wrappers for keys and nonces
- Enable all compiler warnings and clippy lints
- Run tests with
--releaseflag for accurate benchmarks - Use
#[must_use]for functions returningResult
Troubleshooting
Common Issues
- Compilation Errors
# Clear cargo cache cargo clean # Update dependencies cargo update # Check for conflicting features cargo tree -d - Performance Issues
// Enable optimizations #[cfg(not(debug_assertions))] compile_error!("This crate should be compiled in release mode"); // Check CPU features if is_x86_feature_detected!("aes") { // Use AES-NI } - Memory Leaks
// Use Valgrind or AddressSanitizer RUSTFLAGS="-Z sanitizer=address" cargo test