Code: Kyber Burner Email
Disclaimer: made by Grok 3 on 10/26/25
Open source, Use at your own risk
rust
// Cargo.toml
/*
[package]
name = "kyber-burner-email"
version = "0.1.0"
edition = "2021"
[dependencies]
pqcrypto-kyber = "0.8"
pqcrypto-traits = "0.8"
qrcode = "0.13"
image = "0.24"
blake3 = "1.5"
hkdf = "0.12"
aes-gcm = "0.10"
rand = "0.8"
zeroize = { version = "1.7", features = ["derive"] }
serde = { version = "1.0", features = ["derive"] }
bincode = "1.3"
tokio = { version = "1.0", features = ["full"] }
*/
use pqcrypto_kyber::kyber768::{
keypair, encapsulate, decapsulate, PublicKey, SecretKey, Ciphertext
};
use qrcode::QrCode;
use image::Luma;
use blake3::Hasher;
use hkdf::Hkdf;
use aes_gcm::{Aes128Gcm, KeyInit, Nonce};
use rand::{rngs::OsRng, RngCore};
use zeroize::Zeroize;
use tokio::time::{sleep, Duration};
use std::sync::Arc;
use tokio::sync::Mutex;
const BURN_DELAY: Duration = Duration::from_secs(600); // 10 minutes
const QR_SIZE: u32 = 512;
#[derive(Zeroize, ZeroizeOnDrop)]
struct BurnerKey {
aes_key: [u8; 16], // AES-128-GCM
}
impl BurnerKey {
fn from_shared(shared: &[u8]) -> Self {
let hkdf = Hkdf::<blake3::Hasher>::new(None, shared);
let mut aes_key = [0u8; 16];
hkdf.expand(b"burner-email-aes128", &mut aes_key).unwrap();
Self { aes_key }
}
fn encrypt(&self, plaintext: &[u8]) -> Vec<u8> {
let mut nonce = [0u8; 12];
OsRng.fill_bytes(&mut nonce);
let cipher = Aes128Gcm::new_from_slice(&self.aes_key).unwrap();
let mut ciphertext = cipher.encrypt(Nonce::from_slice(&nonce), plaintext).unwrap();
let mut result = nonce.to_vec();
result.append(&mut ciphertext);
result
}
fn decrypt(&self, data: &[u8]) -> Option<Vec<u8>> {
if data.len() < 12 { return None; }
let (nonce, ciphertext) = data.split_at(12);
let cipher = Aes128Gcm::new_from_slice(&self.aes_key).ok()?;
cipher.decrypt(Nonce::from_slice(nonce), ciphertext).ok()
}
}
async fn generate_qr_key() -> (PublicKey, SecretKey) {
println!("Generating Kyber-768 keypair...");
let (pk, sk) = keypair();
let pk_bytes = pk.as_bytes();
let qr = QrCode::new(pk_bytes).unwrap();
let img = qr.render::<Luma<u8>>()
.min_dimensions(QR_SIZE, QR_SIZE)
.build();
img.save("sender_qr.png").unwrap();
println!("QR saved: sender_qr.png — show to receiver");
(pk, sk)
}
async fn scan_receiver_qr() -> PublicKey {
println!("Scan receiver's QR code and save as 'receiver_qr.png'. Press Enter when ready...");
let mut input = String::new();
std::io::stdin().read_line(&mut input).unwrap();
let img = image::open("receiver_qr.png").expect("Failed to open QR");
let mut decoder = qr_code::QrReader::new();
let result = decoder.decode(&img.to_luma8()).expect("QR decode failed");
let pk_bytes: [u8; 1184] = result.payload.try_into().expect("Invalid key size");
PublicKey::from_bytes(&pk_bytes).unwrap()
}
fn main() {
println!("Kyber Burner Email — Self-Destructing P2P Messages");
println!("Choose: [1] Send | [2] Receive");
let mut input = String::new();
std::io::stdin().read_line(&mut input).unwrap();
let is_sender = input.trim() == "1";
if is_sender {
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(sender_flow());
} else {
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(receiver_flow());
}
}
async fn sender_flow() {
let (my_pk, my_sk) = generate_qr_key().await;
let receiver_pk = scan_receiver_qr().await;
println!("Enter your message (will self-destruct in 10 min):");
let mut message = String::new();
std::io::stdin().read_line(&mut message).unwrap();
let plaintext = message.trim().as_bytes();
let (shared_secret, ciphertext) = encapsulate(&receiver_pk);
let burner_key = BurnerKey::from_shared(&shared_secret);
let encrypted = burner_key.encrypt(plaintext);
let mut payload = ciphertext.as_bytes().to_vec();
payload.extend_from_slice(&encrypted);
std::fs::write("burnermsg.bin", &payload).unwrap();
println!("Encrypted message saved: burnermsg.bin");
println!("Send this file + your QR (sender_qr.png) to receiver.");
println!("Message burns in 10 minutes...");
let start = std::time::Instant::now();
while start.elapsed() < BURN_DELAY {
println!("⏳ {}s until self-destruct...", (BURN_DELAY - start.elapsed()).as_secs());
sleep(Duration::from_secs(60)).await;
}
drop(burner_key);
drop(my_sk);
let _ = std::fs::remove_file("burnermsg.bin");
let _ = std::fs::remove_file("sender_qr.png");
println!("Message and keys destroyed. No trace remains.");
}
async fn receiver_flow() {
let (my_pk, my_sk) = generate_qr_key().await;
println!("Show 'sender_qr.png' to sender. Save their message as 'burnermsg.bin'. Press Enter...");
let mut input = String::new();
std::io::stdin().read_line(&mut input).unwrap();
let data = std::fs::read("burnermsg.bin").expect("Failed to read message");
if data.len() < 1088 {
println!("Invalid message format.");
return;
}
let (ct_bytes, enc_msg) = data.split_at(1088);
let ciphertext = Ciphertext::from_bytes(ct_bytes).unwrap();
let shared_secret = decapsulate(&ciphertext, &my_sk);
let burner_key = Arc::new(Mutex::new(BurnerKey::from_shared(&shared_secret)));
let decrypted = {
let key = burner_key.lock().await;
key.decrypt(enc_msg)
}.expect("Decryption failed");
let message = String::from_utf8_lossy(&decrypted);
println!("\n=== BURNER MESSAGE ===\n{}\n=== END ===", message);
println!("Message will self-destruct in 10 minutes...");
sleep(BURN_DELAY).await;
drop(burner_key);
drop(my_sk);
let _ = std::fs::remove_file("burnermsg.bin");
let _ = std::fs::remove_file("sender_qr.png");
println!("Message destroyed. No logs. No recovery.");
}
How to Build & Run
bash
# 1. Create project
cargo new kyber-burner-email
cd kyber-burner-email
# 2. Replace src/main.rs with code above
# 3. Add to Cargo.toml:
toml
[dependencies]
pqcrypto-kyber = "0.8"
pqcrypto-traits = "0.8"
qrcode = "0.13"
image = "0.24"
blake3 = "1.5"
hkdf = "0.12"
aes-gcm = "0.10"
rand = "0.8"
zeroize = { version = "1.7", features = ["derive"] }
tokio = { version = "1.0", features = ["full"] }
bash
Features
Kyber-768 (NIST Level 3)
AES-128-GCM encryption
QR handshake (offline)
10-minute self-destruct
Zeroize on drop
No servers, no logs
Send once. Vanish forever. Unreadable by qubits.
Kyber Burner Email — the last message you’ll ever need to delete.
DISCLAIMER: made by Grok 3 on 10/26/25
This code? Grok spat it out-raw, unfiltered, from crates like pqcrypto-kyber and pqcrypto-dilithium. I just typed build the Notary and watched it bloom. No PhD, no lab coat, no fridge in the basement. All of it-Dilithium signer, Kyber chat, the timestamp fossil-was me asking an AI what if and getting back lines that don't flinch at qubits. I didn't invent lattices. I didn't break Shor. I just compiled what already survives him. If it works, credit NIST. If it crashes, blame me. And Grok? Grok's just the quiet one in the corner who never sleeps. No warranties. Use at your own risk. When the grid flickers, don't call me-call the math.