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.

move tree sig verification to utils

+81 -45
+5 -42
src/raw/verify.rs
··· 2 2 3 3 use std::path::PathBuf; 4 4 5 - use anyhow::{Context, Result}; 5 + use anyhow::Result; 6 6 use git2::{Oid, Repository}; 7 - use libsignify::{Codeable, PublicKey, Signature}; 7 + use libsignify::PublicKey; 8 8 9 9 use crate::utils; 10 10 ··· 26 26 tree_rev: &str, 27 27 recover: bool, 28 28 ) -> Result<Option<Oid>> { 29 - let oid = repo 30 - .revparse_single(tree_rev) 31 - .context("Failed to look-up git tree oid")? 32 - .id(); 33 - let tree = repo 34 - .find_tree(oid) 35 - .context("No tree object found for the given revision")?; 36 - 37 - let object = tree 38 - .get_name("object") 39 - .context("Failed to look-up signed object in the tree")? 40 - .to_object(repo) 41 - .context("The signed object could not be retrieved")?; 42 - let object = object 43 - .as_blob() 44 - .context("The signed object is not a blob")?; 45 - let dereferenced_obj = object.content(); 46 - 47 - let signature = { 48 - let signature = tree 49 - .get_name("signature") 50 - .context("Failed to look-up signature in the tree")? 51 - .to_object(repo) 52 - .context("The signature object could not be retrieved")?; 53 - let signature = signature 54 - .as_blob() 55 - .context("The signature object is not a blob")?; 56 - Signature::from_bytes(signature.content()) 57 - .map_err(utils::Error::new) 58 - .context("Failed to parse signature")? 59 - }; 60 - 61 - public_key 62 - .verify(dereferenced_obj, &signature) 63 - .map_err(utils::Error::new) 64 - .context("Failed to verify signature")?; 65 - 66 - recover 67 - .then(|| Oid::from_bytes(dereferenced_obj).context("Failed to parse git object id")) 68 - .transpose() 29 + let tree_sig = utils::TreeSignature::load(repo, tree_rev)?; 30 + tree_sig.verify(public_key)?; 31 + recover.then(|| tree_sig.dereference()).transpose() 69 32 }
+76 -3
src/utils.rs
··· 4 4 use std::fmt; 5 5 use std::path::PathBuf; 6 6 7 - use anyhow::{Context, Result}; 8 - use git2::{ObjectType, Oid, Repository, RepositoryOpenFlags}; 9 - use libsignify::{Codeable, PrivateKey, PublicKey}; 7 + use anyhow::{anyhow, Context, Result}; 8 + use git2::{Blob, ObjectType, Oid, Repository, RepositoryOpenFlags}; 9 + use libsignify::{Codeable, PrivateKey, PublicKey, Signature}; 10 10 use zeroize::Zeroizing; 11 + 12 + /// A signature stored in a git tree object. 13 + pub struct TreeSignature<'repo> { 14 + /// Pointer to the object that was signed. 15 + pub object_pointer: Blob<'repo>, 16 + /// The signature over the git object. 17 + pub signature: Signature, 18 + } 19 + 20 + impl<'repo> TreeSignature<'repo> { 21 + /// Load a [`TreeSignature`] at the given `tree_rev` from the 22 + /// provided git repository. 23 + #[inline] 24 + pub fn load(repo: &'repo Repository, tree_rev: &str) -> Result<Self> { 25 + let oid = repo 26 + .revparse_single(tree_rev) 27 + .context("Failed to look-up git tree oid")? 28 + .id(); 29 + Self::load_oid(repo, oid) 30 + } 31 + 32 + /// Like [`TreeSignature::load`], but uses a concrete revision pointing 33 + /// to the tree signature. 34 + pub fn load_oid(repo: &'repo Repository, oid: Oid) -> Result<Self> { 35 + let tree = repo 36 + .find_tree(oid) 37 + .context("No tree object found for the given revision")?; 38 + 39 + let object = tree 40 + .get_name("object") 41 + .context("Failed to look-up signed object in the tree")? 42 + .to_object(repo) 43 + .context("The signed object could not be retrieved")?; 44 + let object_pointer = match object.into_blob() { 45 + Ok(ptr) => ptr, 46 + Err(_) => return Err(anyhow!("The signed object is not a blob")), 47 + }; 48 + 49 + let signature = { 50 + let signature = tree 51 + .get_name("signature") 52 + .context("Failed to look-up signature in the tree")? 53 + .to_object(repo) 54 + .context("The signature object could not be retrieved")?; 55 + let signature = signature 56 + .as_blob() 57 + .context("The signature object is not a blob")?; 58 + Signature::from_bytes(signature.content()) 59 + .map_err(Error::new) 60 + .context("Failed to parse signature")? 61 + }; 62 + 63 + Ok(Self { 64 + signature, 65 + object_pointer, 66 + }) 67 + } 68 + 69 + /// Verify the authenticity of this [`TreeSignature`]. 70 + pub fn verify(&self, public_key: &PublicKey) -> Result<()> { 71 + let dereferenced_obj = self.object_pointer.content(); 72 + public_key 73 + .verify(dereferenced_obj, &self.signature) 74 + .map_err(Error::new) 75 + .context("Failed to verify signature") 76 + } 77 + 78 + /// Dereference the inner object pointer. 79 + #[inline] 80 + pub fn dereference(&self) -> Result<Oid> { 81 + Oid::from_bytes(self.object_pointer.content()).context("Failed to parse git object id") 82 + } 83 + } 11 84 12 85 /// An error type. 13 86 #[derive(Debug)]