main.rs
1 use pqcrypto_kyber::kyber1024; 2 use pqcrypto_traits::kem::{SecretKey, Ciphertext, SharedSecret}; 3 use std::fs; 4 use std::path::PathBuf; 5 use std::io::{self, Write}; 6 use hex; 7 use aes_gcm::{Aes256Gcm, Nonce, aead::{Aead, KeyInit, Payload}}; 8 use sha3::{Shake256, Sha3_256, digest::{ExtendableOutput, Update, XofReader, Digest}}; 9 use zeroize::Zeroize; 10 11 fn main() -> Result<(), Box<dyn std::error::Error>> { 12 println!("=== GHOSTLINE OTP RECEIVER (QUANTUM-SAFE) ==="); 13 println!("For friends to decrypt OTPs from GhostLine admin\n"); 14 15 // 1. GET SECRET KEY 16 println!("1. 🔑 YOUR SECRET KEY"); 17 print!("Path to your Kyber secret.key: "); 18 io::stdout().flush()?; 19 let mut secret_path = String::new(); 20 io::stdin().read_line(&mut secret_path)?; 21 let secret_path = secret_path.trim(); 22 23 let secret_bytes = fs::read(secret_path) 24 .map_err(|e| format!("Failed to read secret key: {}", e))?; 25 let my_secret = kyber1024::SecretKey::from_bytes(&secret_bytes) 26 .map_err(|e| format!("Invalid secret key format: {}", e))?; 27 println!("✅ Loaded secret key"); 28 29 // 2. GET YOUR PACKAGE FILES 30 println!("\n2. 📁 YOUR PACKAGE FROM GHOSTLINE ADMIN"); 31 32 print!("Directory containing your package: "); 33 io::stdout().flush()?; 34 let mut package_dir = String::new(); 35 io::stdin().read_line(&mut package_dir)?; 36 let package_dir = package_dir.trim(); 37 38 print!("Directory containing common files: "); 39 io::stdout().flush()?; 40 let mut common_dir = String::new(); 41 io::stdin().read_line(&mut common_dir)?; 42 let common_dir = common_dir.trim(); 43 44 // 3. LOAD YOUR FILES 45 println!("\n3. 🔍 LOADING FILES..."); 46 47 let kyber_ct_path = PathBuf::from(package_dir).join("kyber_ciphertext.bin"); 48 let wrapped_key_path = PathBuf::from(package_dir).join("wrapped_aes_key.bin"); 49 let wrap_nonce_path = PathBuf::from(package_dir).join("wrap_nonce.bin"); 50 51 let ct_bytes = fs::read(&kyber_ct_path) 52 .map_err(|e| format!("Failed to read kyber_ciphertext.bin: {}", e))?; 53 println!("✅ Kyber ciphertext: {} bytes", ct_bytes.len()); 54 55 let wrapped_aes_key = fs::read(&wrapped_key_path) 56 .map_err(|e| format!("Failed to read wrapped_aes_key.bin: {}", e))?; 57 println!("✅ Wrapped AES key: {} bytes", wrapped_aes_key.len()); 58 59 let wrap_nonce_data = fs::read(&wrap_nonce_path) 60 .map_err(|e| format!("Failed to read wrap_nonce.bin: {}", e))?; 61 println!("✅ Wrap nonce: {} bytes", wrap_nonce_data.len()); 62 63 // 4. LOAD COMMON FILES 64 let encrypted_otp_path = PathBuf::from(common_dir).join("encrypted_otp.bin"); 65 let aes_nonce_path = PathBuf::from(common_dir).join("aes_nonce.bin"); 66 67 let encrypted_otp = fs::read(&encrypted_otp_path) 68 .map_err(|e| format!("Failed to read encrypted_otp.bin: {}", e))?; 69 println!("✅ Encrypted OTP: {} bytes", encrypted_otp.len()); 70 71 let aes_nonce_data = fs::read(&aes_nonce_path) 72 .map_err(|e| format!("Failed to read aes_nonce.bin: {}", e))?; 73 println!("✅ AES nonce: {} bytes", aes_nonce_data.len()); 74 75 // 5. DECRYPT KYBER TO GET SHARED SECRET 76 println!("\n4. 🔐 DECRYPTING KYBER CIPHERTEXT"); 77 let ciphertext = kyber1024::Ciphertext::from_bytes(&ct_bytes) 78 .map_err(|e| format!("Invalid Kyber ciphertext: {}", e))?; 79 let shared_secret = kyber1024::decapsulate(&ciphertext, &my_secret); 80 let secret_bytes = shared_secret.as_bytes(); 81 82 println!("✅ Recovered shared secret: {}...", hex::encode(&secret_bytes[..8])); 83 84 // 6. DERIVE WRAP KEY WITH SHAKE256 - MUST MATCH ADMIN EXACTLY 85 println!("\n5. 🔑 DERIVING WRAP KEY (SHAKE256)"); 86 87 let mut shake = Shake256::default(); 88 Update::update(&mut shake, secret_bytes); 89 Update::update(&mut shake, b"GHOSTLINE-AES-KEY-WRAP-v1"); 90 Update::update(&mut shake, &ct_bytes[..32]); 91 // NO OTP SIZE - MUST MATCH ADMIN EXACTLY! 92 93 let mut wrap_key = [0u8; 32]; 94 let mut reader = shake.finalize_xof(); 95 reader.read(&mut wrap_key); 96 97 println!("✅ Wrap key derived: {}...", hex::encode(&wrap_key[..8])); 98 99 // 7. DECRYPT THE WRAPPED AES KEY 100 println!("\n6. 🔓 UNWRAPPING AES KEY"); 101 102 let wrap_cipher = Aes256Gcm::new_from_slice(&wrap_key)?; 103 let wrap_nonce = Nonce::from_slice(&wrap_nonce_data); 104 105 let payload = Payload { 106 msg: &wrapped_aes_key, 107 aad: b"", 108 }; 109 110 let aes_key_vec = wrap_cipher.decrypt(wrap_nonce, payload) 111 .map_err(|e| format!("Failed to unwrap AES key: {}", e))?; 112 113 if aes_key_vec.len() != 32 { 114 return Err(format!("Invalid AES key length: {} bytes", aes_key_vec.len()).into()); 115 } 116 117 let mut aes_key = [0u8; 32]; 118 aes_key.copy_from_slice(&aes_key_vec[..32]); 119 120 println!("✅ AES-256 key recovered: {}...", hex::encode(&aes_key[..8])); 121 122 // 8. DECRYPT OTP WITH AES KEY 123 println!("\n7. 🔓 DECRYPTING OTP"); 124 125 let cipher = Aes256Gcm::new_from_slice(&aes_key)?; 126 let aes_nonce = Nonce::from_slice(&aes_nonce_data); 127 128 let payload = Payload { 129 msg: &encrypted_otp, 130 aad: b"", 131 }; 132 133 let decrypted_otp = cipher.decrypt(aes_nonce, payload) 134 .map_err(|e| format!("Failed to decrypt OTP: {}", e))?; 135 136 println!("✅ OTP decrypted: {} bytes", decrypted_otp.len()); 137 138 // 9. SAVE OTP 139 println!("\n8. 💾 SAVING DECRYPTED OTP"); 140 141 let output_path = "./ghostline_otp.bin"; 142 fs::write(output_path, &decrypted_otp)?; 143 144 println!("✅ OTP saved to: {}", output_path); 145 146 // 10. VERIFICATION WITH SHA3-256 147 println!("\n9. ✅ VERIFICATION"); 148 149 let mut hasher = Sha3_256::new(); 150 Update::update(&mut hasher, &decrypted_otp); 151 let otp_hash = hasher.finalize(); 152 153 println!("OTP SHA3-256 hash: {}", hex::encode(otp_hash)); 154 println!("Share this hash with GhostLine admin to verify ALL friends got same OTP."); 155 156 // 11. CLEAR SENSITIVE DATA 157 wrap_key.zeroize(); 158 aes_key.zeroize(); 159 160 println!("\n=== READY FOR GHOSTLINE ==="); 161 println!("Run GhostLine with this OTP:"); 162 println!(" ghostline --otp {}", output_path); 163 164 Ok(()) 165 }