use anyhow::{Result, Context};
use std::fs;
use std::path::Path;
#[tokio::main]
async fn main() -> Result<()> {
println!("\n╔══════════════════════════════════════════════════════════════╗");
println!("║ View Encrypted Chat Data & Decryption Example ║");
println!("╚══════════════════════════════════════════════════════════════╝\n");
let data_path = "./example-enhanced-chat-data";
let file_path = format!("{}/qdrant-data/cudewvsbxakj1n/chat_history-documents.json", data_path);
println!("📂 Data Directory: {}", data_path);
println!("📄 Chat File: {}\n", file_path);
if !Path::new(&file_path).exists() {
println!("❌ Chat history file not found!");
println!("\n💡 To create sample data, run:");
println!(" cargo run --example show_chat_storage_format\n");
return Ok(());
}
let file_content = fs::read_to_string(&file_path)
.context("Failed to read chat history file")?;
println!("╔══════════════════════════════════════════════════════════════╗");
println!("║ RAW ENCRYPTED FILE CONTENTS (EXACT JSON FORMAT) ║");
println!("╚══════════════════════════════════════════════════════════════╝\n");
let total_lines = file_content.lines().filter(|l| !l.trim().is_empty()).count();
println!("File contains {} documents\n", total_lines);
for (i, line) in file_content.lines().enumerate() {
if line.trim().is_empty() {
continue;
}
println!("─────────────────────────────────────────────────────────────");
println!("Document #{}", i + 1);
println!("─────────────────────────────────────────────────────────────");
match serde_json::from_str::<serde_json::Value>(line) {
Ok(json) => {
println!("{}\n", serde_json::to_string_pretty(&json)?);
}
Err(_) => {
println!("{}\n", line);
}
}
}
println!("\n╔══════════════════════════════════════════════════════════════╗");
println!("║ DECRYPTED DATA (ALL CONVERSATIONS) ║");
println!("╚══════════════════════════════════════════════════════════════╝\n");
use rag_module::RagModule;
let rag = RagModule::new(data_path).await?;
rag.initialize().await?;
println!("✅ Decryption service initialized\n");
println!("🔓 Decrypting all chat history data...\n");
match rag.get_decrypted_chat_history("cudewvsbxakj1n").await {
Ok(decrypted_data) => {
println!("╔══════════════════════════════════════════════════════════════╗");
println!("║ COMPLETE DECRYPTED DATA (EXACT JSON FORMAT) ║");
println!("╚══════════════════════════════════════════════════════════════╝\n");
println!("{}\n", serde_json::to_string_pretty(&decrypted_data)?);
}
Err(e) => {
println!("❌ Decryption failed: {}\n", e);
}
}
println!("╔══════════════════════════════════════════════════════════════╗");
println!("║ ENCRYPTION DETAILS ║");
println!("╚══════════════════════════════════════════════════════════════╝\n");
println!("Encryption Scheme: AES-256-GCM");
println!("Key Length: 256 bits (32 bytes)");
println!("Nonce Length: 96 bits (12 bytes)");
println!("Tag Length: 128 bits (16 bytes)\n");
println!("Key Storage:");
println!(" Primary: macOS Keychain (OS-level security)");
println!(" Backup: {}/keys/ directory (encrypted)", data_path);
println!(" Keys: main_key, embedding_key, sync_key\n");
println!("Encrypted Content Format:");
println!(" Base64 encoded string containing:");
println!(" - Nonce (12 bytes)");
println!(" - Ciphertext (variable length)");
println!(" - Authentication tag (16 bytes)\n");
println!("Decryption Process:");
println!(" 1. Retrieve encryption key from keychain");
println!(" 2. Decode Base64 encrypted content");
println!(" 3. Extract nonce, ciphertext, and tag");
println!(" 4. Decrypt using AES-256-GCM");
println!(" 5. Verify authentication tag");
println!(" 6. Return plaintext message\n");
println!("✅ Example completed!");
println!("\n📚 Summary:");
println!(" • Encrypted data is stored in: {}", file_path);
println!(" • Each message is encrypted separately");
println!(" • Decryption is automatic when using search_chat_history()");
println!(" • Encryption keys are securely stored in macOS Keychain\n");
Ok(())
}