use anyhow::{Context, Result};
use firecloud_crypto::{generate_salt, Kek, SALT_SIZE};
use std::io::{self, Write};
pub fn prompt_password_with_confirmation(prompt: &str) -> Result<String> {
loop {
let password = rpassword::prompt_password(prompt)
.context("Failed to read password")?;
if password.is_empty() {
eprintln!("❌ Password cannot be empty. Please try again.");
continue;
}
if password.len() < 8 {
eprintln!("⚠️ Warning: Password is too short (< 8 characters). Recommended: 12+ characters.");
}
let confirm = rpassword::prompt_password("Confirm password: ")
.context("Failed to read password confirmation")?;
if password == confirm {
return Ok(password);
}
eprintln!("❌ Passwords don't match. Please try again.\n");
}
}
pub fn prompt_password(prompt: &str) -> Result<String> {
rpassword::prompt_password(prompt)
.context("Failed to read password")
}
pub fn prompt_use_encryption() -> Result<bool> {
print!("🔐 Encrypt this file with a password? [Y/n]: ");
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
let answer = input.trim().to_lowercase();
Ok(answer.is_empty() || answer == "y" || answer == "yes")
}
pub fn derive_kek_with_new_salt(password: &str) -> Result<(Kek, [u8; SALT_SIZE])> {
let salt = generate_salt();
let kek = Kek::derive_from_password(password, &salt)
.context("Failed to derive encryption key from password")?;
Ok((kek, salt))
}
pub fn derive_kek(password: &str, salt: &[u8]) -> Result<Kek> {
if salt.len() != SALT_SIZE {
anyhow::bail!("Invalid salt size: expected {}, got {}", SALT_SIZE, salt.len());
}
let salt_array: [u8; SALT_SIZE] = salt.try_into()
.context("Failed to convert salt to array")?;
Kek::derive_from_password(password, &salt_array)
.context("Failed to derive encryption key from password")
}