use std::ffi::OsString; use std::io::Write; use std::path::{Path, PathBuf}; use std::process::Command; use anyhow::{Context, Result}; pub struct KeyPair { pub private_key: PathBuf, pub public_key: PathBuf, } impl KeyPair { pub fn new(public_key: &Path, private_key: &Path) -> Self { Self { public_key: public_key.into(), private_key: private_key.into(), } } pub fn sign_and_copy(&self, from: &Path, to: &Path) -> Result<()> { let args: Vec = vec![ OsString::from("--key"), self.private_key.clone().into(), OsString::from("--cert"), self.public_key.clone().into(), from.as_os_str().to_owned(), OsString::from("--output"), to.as_os_str().to_owned(), ]; let output = Command::new("sbsign").args(&args).output()?; if !output.status.success() { std::io::stderr() .write_all(&output.stderr) .context("Failed to write output of sbsign to stderr.")?; log::debug!("sbsign failed with args: `{args:?}`."); return Err(anyhow::anyhow!("Failed to sign {to:?}.")); } Ok(()) } /// Verify the signature of a PE binary. Return true if the signature was verified. pub fn verify(&self, path: &Path) -> bool { let args: Vec = vec![ OsString::from("--cert"), self.public_key.clone().into(), path.as_os_str().to_owned(), ]; let output = match Command::new("sbverify").args(&args).output() { Ok(output) => output, Err(_) => return false, }; if !output.status.success() { if std::io::stderr().write_all(&output.stderr).is_err() { return false; }; log::debug!("sbverify failed with args: `{args:?}`."); return false; } true } }