use crate::commands::command::Cmd;
use crate::error::KeyToolError;
use crate::utils::fake_cert::generate_fake_cert;
use clap::Args;
use openssl::pkcs12::Pkcs12;
use openssl::pkey::PKey;
use std::fs;
#[derive(Args, Debug, Clone)]
pub struct GenSecKeyCmd {
#[arg(long)]
pub alias: String,
#[arg(long, default_value = "AES")]
pub keyalg: String,
#[arg(long)]
pub keysize: Option<u32>,
#[arg(long)]
pub keystore: String,
#[arg(long, default_value = "PKCS12")]
pub storetype: String,
#[arg(long)]
pub storepass: String,
}
impl Cmd for GenSecKeyCmd {
fn run(&self) -> Result<(), KeyToolError> {
if self.storetype.to_uppercase() != "PKCS12" {
return Err(KeyToolError::new(
"Only PKCS12 storetype is supported (like Java keytool)",
));
}
let keysize = self.keysize.unwrap_or_else(|| {
match self.keyalg.to_uppercase().as_str() {
"AES" => 256,
"HMACSHA256" => 256,
_ => 256, }
});
let key_bytes = keysize / 8;
let mut key_data = vec![0u8; key_bytes as usize];
openssl::rand::rand_bytes(&mut key_data)
.map_err(|e| KeyToolError::new(format!("Failed to generate key: {}", e)))?;
let pkey = PKey::hmac(&key_data)
.map_err(|e| KeyToolError::new(format!("Failed to create PKey: {}", e)))?;
let (cert, pkey) = generate_fake_cert(&self.alias)?;
let pkcs12 = Pkcs12::builder()
.name(&self.alias)
.pkey(&pkey) .cert(&cert) .build2(&self.storepass)?;
fs::write(&self.keystore, pkcs12.to_der().unwrap())
.map_err(|e| KeyToolError::new(format!("Failed to save keystore: {}", e)))?;
println!("Generated secret key entry with alias {}", self.alias);
println!("Keystore stored at: {}", self.keystore);
println!("Key algorithm: {}", self.keyalg);
println!("Key size: {} bits", keysize);
println!("Storetype: PKCS12");
Ok(())
}
}