use paseto_pq::{Claims, KeyPair, PasetoPQ};
use std::time::Instant;
use time::{Duration, OffsetDateTime};
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("๐ PASETO-PQ Performance Demo");
println!("================================================\n");
println!("๐ Key Generation:");
let mut rng = rand::rng();
let keygen_start = Instant::now();
let keypair = KeyPair::generate(&mut rng);
let keygen_time = keygen_start.elapsed();
println!(" ML-DSA KeyGen: {:?}", keygen_time);
println!(" Note: Ed25519 typically takes ~50-100ยตs\n");
let signing_bytes = keypair.signing_key_to_bytes();
let verifying_bytes = keypair.verifying_key_to_bytes();
println!("๐๏ธ Key Sizes:");
println!(" Signing key: {} bytes", signing_bytes.len());
println!(" Verifying key: {} bytes", verifying_bytes.len());
println!(" Note: Ed25519 keys are 32 bytes each\n");
let mut claims = Claims::new();
claims.set_subject("user123")?;
claims.set_issuer("my-service")?;
claims.set_audience("api.example.com")?;
claims.set_expiration(OffsetDateTime::now_utc() + Duration::hours(1))?;
claims.set_jti("unique-token-123")?;
claims.add_custom("tenant_id", "org_abc123")?;
claims.add_custom("roles", ["user", "admin"])?;
claims.add_custom("permissions", ["read:messages", "write:messages"])?;
println!("โ๏ธ Token Signing:");
let sign_start = Instant::now();
let token = PasetoPQ::sign(keypair.signing_key(), &claims)?;
let sign_time = sign_start.elapsed();
println!(" ML-DSA Sign: {:?}", sign_time);
println!(" Note: Ed25519 typically takes ~20-50ยตs\n");
println!("๐ Token Size:");
println!(" Token length: {} bytes", token.len());
println!(" Note: Ed25519 PASETO tokens are typically ~300-500 bytes\n");
println!("โ
Token Verification:");
let verify_start = Instant::now();
let verified = PasetoPQ::verify(keypair.verifying_key(), &token)?;
let verify_time = verify_start.elapsed();
println!(" ML-DSA Verify: {:?}", verify_time);
println!(" Note: Ed25519 typically takes ~40-80ยตs\n");
println!("๐ Batch Operations (100 iterations):");
let batch_sign_start = Instant::now();
let mut tokens = Vec::new();
for i in 0..100 {
let mut batch_claims = Claims::new();
batch_claims.set_subject(format!("user{}", i))?;
batch_claims.set_issuer("my-service")?;
batch_claims.set_audience("api.example.com")?;
batch_claims.set_jti(format!("token-{}", i))?;
let batch_token = PasetoPQ::sign(keypair.signing_key(), &batch_claims)?;
tokens.push(batch_token);
}
let batch_sign_time = batch_sign_start.elapsed();
println!(
" 100 signs: {:?} ({:?} per operation)",
batch_sign_time,
batch_sign_time / 100
);
let batch_verify_start = Instant::now();
for token in &tokens {
let _verified = PasetoPQ::verify(keypair.verifying_key(), token)?;
}
let batch_verify_time = batch_verify_start.elapsed();
println!(
" 100 verifies: {:?} ({:?} per operation)",
batch_verify_time,
batch_verify_time / 100
);
println!("\n๐ซ Sample PASETO-PQ Token:");
if token.len() > 200 {
println!(" paseto.v1.public.{}...", &token[13..200]);
println!(" (truncated - full length: {} chars)", token.len());
} else {
println!(" {}", token);
}
println!("\n๐ Verified Claims:");
let claims = verified.claims();
println!(" Subject: {:?}", claims.subject());
println!(" Issuer: {:?}", claims.issuer());
println!(" Audience: {:?}", claims.audience());
println!(" JTI: {:?}", claims.jti());
if let Some(tenant) = claims.get_custom("tenant_id") {
println!(" Tenant: {:?}", tenant.as_str());
}
if let Some(roles) = claims.get_custom("roles") {
println!(" Roles: {:?}", roles);
}
println!("๐ฏ Performance Summary:");
println!(" โข ML-DSA provides quantum-safe signatures");
println!(" โข ~10-100x slower than Ed25519 (expected for PQ crypto)");
println!(
" โข Signature size depends on parameter set (ml-dsa-44: ~2.4KB, ml-dsa-65: ~3.3KB, ml-dsa-87: ~4.6KB)"
);
println!(" โข Still practical for authentication tokens");
println!(" โข Future-proof against quantum computers");
println!("\nโ
Demo completed successfully!");
Ok(())
}