use serde::Serialize;
use void_core::crypto;
use crate::output::{run_command, CliError, CliOptions};
#[derive(Debug)]
pub struct DecryptArgs {
pub key: String,
pub ciphertext: String,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DecryptOutput {
pub plaintext: String,
}
pub fn run(args: DecryptArgs, opts: &CliOptions) -> Result<(), CliError> {
run_command("decrypt", opts, |_ctx| {
let key_bytes = hex::decode(&args.key)
.map_err(|e| CliError::invalid_args(format!("invalid key hex: {}", e)))?;
if key_bytes.len() != 32 {
return Err(CliError::invalid_args(format!(
"key must be 32 bytes (64 hex chars), got {} bytes",
key_bytes.len()
)));
}
let key: [u8; 32] = key_bytes.try_into().unwrap();
let ciphertext_bytes = hex::decode(&args.ciphertext)
.map_err(|e| CliError::invalid_args(format!("invalid ciphertext hex: {}", e)))?;
let decrypted = crypto::decrypt(&key, &ciphertext_bytes, b"")
.map_err(|e| CliError::encryption_error(format!("decryption failed: {}", e)))?;
let plaintext = String::from_utf8(decrypted).map_err(|e| {
CliError::encryption_error(format!("decrypted data is not valid UTF-8: {}", e))
})?;
Ok(DecryptOutput { plaintext })
})
}