use anyhow::{bail, Context, Result};
use owo_colors::OwoColorize;
use std::fs;
use std::path::Path;
use kx_fides_core::hash::hash_file;
use kx_fides_core::keys::load_keypair;
use kx_fides_core::manifest::{build_manifest, write_manifest};
use kx_fides_core::sign::sign_hash;
use kx_fides_core::timestamp::now_utc;
use super::SignArgs;
pub fn run(args: SignArgs) -> Result<()> {
let media = args.media;
let key_path = args.key;
let out_path = args.out;
let mime = args.mime;
if !Path::new(&media).exists() {
bail!("media file not found: {}", media.display());
}
if !Path::new(&key_path).exists() {
bail!("key file not found: {}", key_path.display());
}
if let Some(parent) = out_path.parent() {
if !parent.as_os_str().is_empty() && !parent.exists() {
fs::create_dir_all(parent)
.with_context(|| format!("failed to create {}", parent.display()))?;
}
}
let kp = load_keypair(key_path.to_str().unwrap())
.with_context(|| format!("failed to load keypair from {}", key_path.display()))?;
let h = hash_file(&media)
.with_context(|| format!("failed to hash {}", media.display()))?;
let sig = sign_hash(&h, &kp).context("failed to sign hash")?;
let ts = now_utc();
let manifest = build_manifest(
&media,
&h,
sig.value,
kp.public_key,
ts,
mime,
None, );
write_manifest(&out_path, &manifest).with_context(|| {
format!(
"failed to write manifest to {}",
out_path.display()
)
})?;
println!(
"{} {}",
"✓ signed".green().bold(),
media.display()
);
println!(
"{} {}",
"→ manifest:".cyan(),
out_path.display()
);
println!("{} {}", "hash:".cyan(), h.value);
println!("{} {}", "alg:".cyan(), h.algorithm);
Ok(())
}