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.

at main 93 lines 3.0 kB view raw
1//! Create signatures with [`libsignify`]. 2 3use std::path::PathBuf; 4 5use anyhow::{Context, Result}; 6use git2::{ObjectType, Oid, Repository}; 7 8use crate::utils; 9 10/// Execute the `raw sign` command. 11pub fn command(key_path: PathBuf, rev: String) -> Result<()> { 12 let repo = utils::open_repository()?; 13 for secret_key in utils::get_secret_keys(key_path)?.into_values() { 14 let tree_oid = sign(&repo, &secret_key, &rev)?; 15 println!("{tree_oid}"); 16 } 17 Ok(()) 18} 19 20/// Sign the revision `rev` with the given secret key, write the results 21/// to `repo` and return the object id of the resulting signature tree. 22pub fn sign(repo: &Repository, secret_key: &utils::PrivateKey, rev: &str) -> Result<Oid> { 23 let object = repo 24 .revparse_single(rev) 25 .context("Failed to look-up git object id")?; 26 27 let object_ptr = object.id(); 28 let object_mode = match object 29 .kind() 30 .context("Failed to determine object kind to sign")? 31 { 32 ObjectType::Blob => 0o100644, 33 ObjectType::Tree => 0o040000, 34 ObjectType::Commit | ObjectType::Tag => 0o160000, 35 ty @ ObjectType::Any => { 36 anyhow::bail!("Unsupported object type {ty}"); 37 } 38 }; 39 40 let commit_author = repo 41 .signature() 42 .context("Failed to retrieve commit author")?; 43 44 let signature = secret_key.sign(object_ptr.as_bytes())?; 45 let signature_blob = repo 46 .blob(&signature) 47 .context("Failed to write signature to the object store")?; 48 49 let version_blob = repo 50 .blob(utils::TreeSignatureVersion::current().as_str().as_bytes()) 51 .context("Failed to write tree signature version to the object store")?; 52 53 let algo_blob = repo 54 .blob(secret_key.algorithm().as_str().as_bytes()) 55 .context("Failed to write tree signature algorithm to the object store")?; 56 57 let mut tree_builder = repo 58 .treebuilder(None) 59 .context("Failed to get a git tree object builder")?; 60 61 tree_builder 62 .insert("version", version_blob, 0o100644) 63 .context("Failed to write version to the tree")?; 64 tree_builder 65 .insert("algorithm", algo_blob, 0o100644) 66 .context("Failed to write algorithm to the tree")?; 67 tree_builder 68 .insert("signature", signature_blob, 0o100644) 69 .context("Failed to write signature to the tree")?; 70 tree_builder 71 .insert("object", object_ptr, object_mode) 72 .context("Failed to write object to the tree")?; 73 74 let tree_oid = tree_builder 75 .write() 76 .context("Failed to write tree to the object store")?; 77 let tree = repo 78 .find_tree(tree_oid) 79 .context("Failed to look-up newly created git tree signature")?; 80 81 let commit_oid = repo 82 .commit( 83 None, 84 &commit_author, 85 &commit_author, 86 &format!("git-signify signature over {rev}"), 87 &tree, 88 &[], 89 ) 90 .context("Failed to create git signature commit")?; 91 92 Ok(commit_oid) 93}