use crate::cli::VerifyArtifactCommand;
use crate::ui::theme::ThemeMap;
use crate::ui::verify_ui;
use anyhow::{Result, anyhow, Context};
use ring::signature::{UnparsedPublicKey, ED25519};
use serde_json::Value;
use std::fs;
use std::io;
use is_terminal::IsTerminal;
pub fn run_verify_artifact_command(opts: &VerifyArtifactCommand, theme_map: &ThemeMap) -> Result<()> {
let enable_colors = io::stdout().is_terminal();
verify_ui::print_verify_start(&opts.verify_artifact, &opts.public_key, theme_map, enable_colors)?;
let artifact_content = fs::read_to_string(&opts.verify_artifact)
.context("Failed to read artifact file")?;
let parsed_json: Value = serde_json::from_str(&artifact_content)
.context("Failed to parse artifact JSON")?;
let data_to_verify: Vec<u8> = match parsed_json.get("data") {
Some(v) => {
if let Some(s) = v.as_str() {
s.as_bytes().to_vec()
} else {
serde_json::to_string(v)
.context("Failed to serialize 'data' object to canonical JSON string for verification")?
.into_bytes()
}
}
None => return Err(anyhow!("Artifact JSON missing 'data' field")),
};
let signature = parsed_json.get("signature")
.and_then(|v| v.as_str())
.and_then(|s| hex::decode(s).ok())
.context("Artifact JSON missing valid 'signature' field")?;
let public_key_bytes = fs::read(&opts.public_key)
.context("Failed to read public key file")?;
let public_key = UnparsedPublicKey::new(&ED25519, &public_key_bytes);
match public_key.verify(&data_to_verify, &signature) {
Ok(_) => {
verify_ui::print_verify_success(theme_map, enable_colors)?;
Ok(())
}
Err(_) => {
verify_ui::print_verify_failure_error(theme_map, enable_colors)?;
Err(anyhow!("Artifact signature verification FAILED."))
}
}
}