Rust Platform Guide
This guide covers the installation, setup, and usage of MetaMUI Crypto Primitives in Rust projects.
Installation
Build from source:
cd metamui-crypto-rust
cargo build --release
To use in your own project, add a path dependency in your Cargo.toml:
[dependencies]
metamui-falcon512 = { path = "../metamui-crypto-rust/metamui-falcon512" }
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 = { path = "../metamui-crypto-rust", features = ["full"] }
# Or select specific features:
metamui-crypto = {
path = "../metamui-crypto-rust",
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 = { path = "../metamui-crypto-rust", 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);
}
}
}
Running Tests
cd metamui-crypto-rust
cargo test
# Cross-language verification
cargo test --test crosslang_test
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
}
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