#![forbid(unsafe_code)]
use kwt::{
codec::{new_claims, Role, Scope},
crypto::MasterKey,
token::KwtToken,
};
fn main() {
println!("╔══════════════════════════════════════════════════════════════╗");
println!("║ KWT — KDL Web Token Example ║");
println!("╚══════════════════════════════════════════════════════════════╝\n");
let master_key = MasterKey::generate().expect("CSPRNG");
println!("[1] Generated 256-bit master key (CSPRNG)");
let mut claims = new_claims("user_882", "api.example.com", 3_600).expect("claims");
claims.roles = vec![Role::Admin, Role::Editor];
claims.scopes = vec![Scope::ReadStats, Scope::WriteLogs];
println!("\n[2] Claims (human-readable KDL view):");
println!(" subject \"{}\"", claims.subject);
println!(" issued {}", claims.issued_at);
println!(" expires {}", claims.expires_at);
println!(" audience \"{}\"", claims.audience);
let role_strs: Vec<_> = claims.roles.iter().map(|r| format!("\"{}\"", r)).collect();
println!(" roles {}", role_strs.join(" "));
let scope_strs: Vec<_> = claims.scopes.iter().map(|s| format!("\"{}\"", s)).collect();
println!(" scopes {}", scope_strs.join(" "));
println!(" jti {}", claims.jti);
let canonical = kwt::codec_encode(&claims).expect("encode failed");
println!("\n[3] Canonical binary payload: {} bytes", canonical.len());
print!(" Hex: ");
for (i, byte) in canonical.iter().enumerate() {
if i > 0 && i % 16 == 0 { print!("\n "); }
print!("{:02x} ", byte);
}
println!();
let token_str = KwtToken::issue(&claims, &master_key).expect("issue failed");
println!("\n[4] Issued KWT token ({} bytes):", token_str.len());
println!(" {}", token_str);
let equivalent_jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiJ1c2VyXzg4MiIsImlhdCI6e30sImV4cCI6e30sImF1ZCI6ImFwaS5leGFtcGxlLmNvbSIsInJvbGVzIjpbImFkbWluIiwiZWRpdG9yIl0sInNjb3BlcyI6WyJyZWFkOnN0YXRzIiwid3JpdGU6bG9ncyJdfQ.\
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c_dbnU9JZFqcT8R0hM9GbwNu3PVMBAlhU8GWfG8dFQ";
println!("\n[5] Size comparison (sample JWT body {} bytes):", equivalent_jwt.len());
println!(" ┌──────────────────────────┬──────────────┐");
println!(" │ Format │ Size (bytes) │");
println!(" ├──────────────────────────┼──────────────┤");
println!(" │ JWT (typical, RS256) │ ~380-420 │");
println!(" │ KWT canonical plaintext │ {:>12} │", canonical.len());
println!(" │ KWT encrypted token │ {:>12} │", token_str.len());
println!(" └──────────────────────────┴──────────────┘");
println!(
"\n Information density: {:.2} bits/byte (JWT baseline: ~1.55 bits/byte)",
(canonical.len() as f64 * 8.0) / token_str.len() as f64
);
println!("\n[6] Validating token...");
match KwtToken::validate(&token_str, &master_key, "api.example.com") {
Ok(validated) => {
println!(" ✓ Authentication tag verified");
println!(" ✓ Payload parsed successfully");
println!(" ✓ Token not expired");
println!(" ✓ Audience matched");
println!("\n Recovered claims:");
println!(" Subject: {}", validated.claims.subject);
println!(" JTI: {}", validated.claims.jti);
let role_strs: Vec<_> = validated.claims.roles.iter().map(|r| r.to_string()).collect();
println!(" Roles: {}", role_strs.join(", "));
}
Err(e) => {
eprintln!(" ✗ Validation failed: {}", e);
std::process::exit(1);
}
}
println!("\n[7] Tamper detection demo...");
let mut tampered = token_str.clone();
let last = tampered.pop().unwrap();
tampered.push(if last == 'A' { 'B' } else { 'A' });
match KwtToken::validate(&tampered, &master_key, "api.example.com") {
Ok(_) => println!(" ✗ ERROR: tampered token was accepted (this should not happen)"),
Err(e) => println!(" ✓ Tampered token correctly rejected: {}", e),
}
println!("\n[8] Wrong-key detection demo...");
let wrong_key = MasterKey::generate().expect("CSPRNG");
match KwtToken::validate(&token_str, &wrong_key, "api.example.com") {
Ok(_) => println!(" ✗ ERROR: token accepted with wrong key (this should not happen)"),
Err(e) => println!(" ✓ Wrong key correctly rejected: {}", e),
}
println!("\n✓ All checks passed.\n");
}