Harness the power of signify(1) to sign arbitrary git objects
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

sign with multiple keys

+119 -52
+5 -3
src/fingerprint.rs
··· 8 8 9 9 /// Execute the `fingerprint` command. 10 10 pub fn command(key_path: PathBuf) -> Result<()> { 11 - let public_key = utils::get_public_key(key_path)?; 12 - let hash = public_key.fingerprint()?; 13 - println!("{hash}"); 11 + for (path, public_key) in utils::get_public_keys(key_path)? { 12 + let hash = public_key.fingerprint()?; 13 + println!("{}:", path.display()); 14 + println!(" - {hash}"); 15 + } 14 16 Ok(()) 15 17 }
+4 -3
src/raw/sign.rs
··· 11 11 /// Execute the `sign` command. 12 12 pub fn command(key_path: PathBuf, rev: String) -> Result<()> { 13 13 let repo = utils::open_repository()?; 14 - let secret_key = utils::get_secret_key(key_path)?; 15 - let tree_oid = sign(&repo, &secret_key, &rev)?; 16 - println!("{tree_oid}"); 14 + for secret_key in utils::get_secret_keys(key_path)?.into_values() { 15 + let tree_oid = sign(&repo, &secret_key, &rev)?; 16 + println!("{tree_oid}"); 17 + } 17 18 Ok(()) 18 19 } 19 20
+5 -4
src/raw/verify.rs
··· 10 10 /// Execute the `verify` command. 11 11 pub fn command(key_path: PathBuf, recover: bool, tree_rev: String) -> Result<()> { 12 12 let repo = utils::open_repository()?; 13 - let public_key = utils::get_public_key(key_path)?; 14 - let recovered_oid = verify(&repo, &public_key, &tree_rev, recover)?; 15 - if let Some(recovered_oid) = recovered_oid { 16 - println!("{recovered_oid}"); 13 + for public_key in utils::get_public_keys(key_path)?.into_values() { 14 + let recovered_oid = verify(&repo, &public_key, &tree_rev, recover)?; 15 + if let Some(recovered_oid) = recovered_oid { 16 + println!("{recovered_oid}"); 17 + } 17 18 } 18 19 Ok(()) 19 20 }
+13 -12
src/rev_lookup.rs
··· 10 10 /// Execute the `rev-lookup` command. 11 11 pub fn command(key_path: PathBuf, rev: String) -> Result<()> { 12 12 let repo = utils::open_repository()?; 13 - let public_key = utils::get_public_key(key_path)?; 14 - let tree_rev = { 15 - let object_oid = repo 16 - .revparse_single(&rev) 17 - .context("Failed to look-up git object")? 18 - .id(); 19 - let key_fingerprint = public_key.fingerprint()?; 20 - utils::craft_signature_reference(key_fingerprint, object_oid) 21 - }; 22 - repo.revparse_single(&tree_rev) 23 - .with_context(|| format!("No signature found for {rev}"))?; 24 - println!("{tree_rev}"); 13 + for public_key in utils::get_public_keys(key_path)?.into_values() { 14 + let tree_rev = { 15 + let object_oid = repo 16 + .revparse_single(&rev) 17 + .context("Failed to look-up git object")? 18 + .id(); 19 + let key_fingerprint = public_key.fingerprint()?; 20 + utils::craft_signature_reference(key_fingerprint, object_oid) 21 + }; 22 + repo.revparse_single(&tree_rev) 23 + .with_context(|| format!("No signature found for {rev}"))?; 24 + println!("{tree_rev}"); 25 + } 25 26 Ok(()) 26 27 }
+20 -16
src/sign.rs
··· 11 11 /// Execute the `sign` command. 12 12 pub fn command(key_path: PathBuf, rev: String) -> Result<()> { 13 13 let repo = utils::open_repository()?; 14 - let secret_key = utils::get_secret_key(key_path)?; 15 - let tree_oid = sign(&repo, &secret_key, &rev)?; 16 - let signed_object = { 17 - let tree_sig = utils::TreeSignature::load_oid(&repo, tree_oid)?; 18 - tree_sig.dereference()? 19 - }; 20 - let key_fingerprint = secret_key.public_key()?.fingerprint()?; 21 - let reference = utils::craft_signature_reference(key_fingerprint, signed_object); 22 - repo.reference( 23 - &reference, tree_oid, 24 - // references to signatures will never change, so it is 25 - // safe to force overwriting faulty references 26 - true, "", 27 - ) 28 - .context("Failed to store reference to signature")?; 29 - println!("Signature stored under: {reference}"); 14 + for (path, secret_key) in utils::get_secret_keys(key_path)? { 15 + let tree_oid = sign(&repo, &secret_key, &rev)?; 16 + let signed_object = { 17 + let tree_sig = utils::TreeSignature::load_oid(&repo, tree_oid)?; 18 + tree_sig.dereference()? 19 + }; 20 + let key_fingerprint = secret_key.public_key()?.fingerprint()?; 21 + let reference = utils::craft_signature_reference(key_fingerprint, signed_object); 22 + repo.reference( 23 + &reference, tree_oid, 24 + // references to signatures will never change, so it is 25 + // safe to force overwriting faulty references 26 + true, "", 27 + ) 28 + .context("Failed to store reference to signature")?; 29 + println!("Signed with key:"); 30 + println!(" - {}", path.display()); 31 + println!("Signature stored under:"); 32 + println!(" - {reference}"); 33 + } 30 34 Ok(()) 31 35 }
+60 -3
src/utils.rs
··· 1 1 //! Catch-all utilities module. 2 2 3 + use std::collections::BTreeMap; 3 4 use std::error; 4 5 use std::fmt; 6 + use std::fs; 5 7 use std::io::Cursor; 6 - use std::path::PathBuf; 8 + use std::path::{Path, PathBuf}; 7 9 8 10 use anyhow::{anyhow, Context, Result}; 9 11 use git2::{Blob, Object, ObjectType, Oid, Repository, RepositoryOpenFlags}; ··· 426 428 } 427 429 } 428 430 431 + /// Read all keys under the given `path` with `read`. 432 + fn read_key_entries<F, T>(ext: &str, path: PathBuf, mut read: F) -> Result<BTreeMap<PathBuf, T>> 433 + where 434 + F: FnMut(&Path) -> Result<T>, 435 + { 436 + let mut keys = BTreeMap::new(); 437 + 438 + for maybe_ent in fs::read_dir(path) 439 + .with_context(|| format!("Failed to query entries in {ext} key directory"))? 440 + { 441 + let ent = 442 + maybe_ent.with_context(|| format!("Failed to read entry in {ext} key directory"))?; 443 + let path = ent.path(); 444 + 445 + if matches!(path.extension().and_then(|p| p.to_str()), Some(e) if e == ext) { 446 + let key = read(&path)?; 447 + keys.insert(path, key); 448 + } 449 + } 450 + 451 + Ok(keys) 452 + } 453 + 454 + /// Read public keys from the given path. If a directory is provided, 455 + /// keys are read from files whose extension is `.pub`. 456 + pub fn get_public_keys(path: PathBuf) -> Result<BTreeMap<PathBuf, PublicKey>> { 457 + let meta = fs::metadata(&path).context("Failed to query public key path metadata")?; 458 + 459 + if meta.is_dir() { 460 + read_key_entries("pub", path, get_public_key) 461 + } else { 462 + get_public_key(&path).map(|key| { 463 + let mut map = BTreeMap::new(); 464 + map.insert(path, key); 465 + map 466 + }) 467 + } 468 + } 469 + 429 470 /// Read a public key from the given path. 430 - pub fn get_public_key(path: PathBuf) -> Result<PublicKey> { 471 + fn get_public_key(path: &Path) -> Result<PublicKey> { 431 472 let key_data = std::fs::read_to_string(path).context("Failed to read public key")?; 432 473 433 474 Ok(match determine_key_format(&key_data)? { ··· 451 492 }) 452 493 } 453 494 495 + /// Read secret keys from the given path. If a directory is provided, 496 + /// keys are read from files whose extension is `.sec`. 497 + pub fn get_secret_keys(path: PathBuf) -> Result<BTreeMap<PathBuf, PrivateKey>> { 498 + let meta = fs::metadata(&path).context("Failed to query secret key path metadata")?; 499 + 500 + if meta.is_dir() { 501 + read_key_entries("sec", path, get_secret_key) 502 + } else { 503 + get_secret_key(&path).map(|key| { 504 + let mut map = BTreeMap::new(); 505 + map.insert(path, key); 506 + map 507 + }) 508 + } 509 + } 510 + 454 511 /// Read a secret key from the given path. 455 - pub fn get_secret_key(path: PathBuf) -> Result<PrivateKey> { 512 + fn get_secret_key(path: &Path) -> Result<PrivateKey> { 456 513 let key_data = std::fs::read_to_string(path) 457 514 .map(Zeroizing::new) 458 515 .context("Failed to read secret key")?;
+12 -11
src/verify.rs
··· 11 11 /// Execute the `verify` command. 12 12 pub fn command(key_path: PathBuf, rev: String) -> Result<()> { 13 13 let repo = utils::open_repository()?; 14 - let public_key = utils::get_public_key(key_path)?; 15 - let tree_rev = { 16 - let object_oid = repo 17 - .revparse_single(&rev) 18 - .context("Failed to look-up git object")? 19 - .id(); 20 - let key_fingerprint = public_key.fingerprint()?; 21 - utils::craft_signature_reference(key_fingerprint, object_oid) 22 - }; 23 - verify(&repo, &public_key, &tree_rev, false)?; 24 - println!("Signature verified successfully"); 14 + for (path, public_key) in utils::get_public_keys(key_path)? { 15 + let tree_rev = { 16 + let object_oid = repo 17 + .revparse_single(&rev) 18 + .context("Failed to look-up git object")? 19 + .id(); 20 + let key_fingerprint = public_key.fingerprint()?; 21 + utils::craft_signature_reference(key_fingerprint, object_oid) 22 + }; 23 + verify(&repo, &public_key, &tree_rev, false)?; 24 + println!("Signature verified successfully with {}", path.display()); 25 + } 25 26 Ok(()) 26 27 }