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.

factor out utils from main.rs

+85 -70
+10 -70
src/main.rs
··· 1 - use std::error; 2 - use std::fmt; 1 + mod utils; 2 + 3 3 use std::path::PathBuf; 4 4 5 5 use anyhow::{Context, Result}; 6 6 use clap::{Parser, Subcommand}; 7 - use git2::{ObjectType, Oid, Repository}; 8 - use libsignify::{Codeable, PrivateKey, PublicKey, Signature}; 9 - use zeroize::Zeroizing; 10 - 11 - #[derive(Debug)] 12 - pub struct Error<E> { 13 - inner: E, 14 - } 7 + use git2::{Oid, Repository}; 8 + use libsignify::{Codeable, Signature}; 15 9 16 10 /// A git sub-command to sign arbitrary objects 17 11 #[derive(Parser)] ··· 102 96 .as_blob() 103 97 .context("The signature object is not a blob")?; 104 98 Signature::from_bytes(signature.content()) 105 - .map_err(Error::new) 99 + .map_err(utils::Error::new) 106 100 .context("Failed to parse signature")? 107 101 }; 108 102 109 - let public_key = get_public_key(key_path)?; 103 + let public_key = utils::get_public_key(key_path)?; 110 104 111 105 public_key 112 106 .verify(dereferenced_obj, &signature) 113 - .map_err(Error::new) 107 + .map_err(utils::Error::new) 114 108 .context("Failed to verify signature")?; 115 109 116 110 if recover { ··· 133 127 .blob(oid.as_bytes()) 134 128 .context("Failed to write object id to the git store")?; 135 129 136 - let secret_key = get_secret_key(key_path)?; 130 + let secret_key = utils::get_secret_key(key_path)?; 137 131 let signature = secret_key.sign(oid.as_bytes()).as_bytes(); 138 132 let signature_blob = repo 139 133 .blob(&signature) ··· 161 155 } 162 156 163 157 fn fingerprint(key_path: PathBuf) -> Result<()> { 164 - let public_key = get_public_key(key_path)?; 165 - let hash = hash_bytes(public_key.key().as_ref())?; 158 + let public_key = utils::get_public_key(key_path)?; 159 + let hash = utils::hash_bytes(public_key.key().as_ref())?; 166 160 println!("{hash}"); 167 161 Ok(()) 168 162 } 169 - 170 - #[inline] 171 - fn hash_bytes(bytes: &[u8]) -> Result<Oid> { 172 - Oid::hash_object(ObjectType::Blob, bytes).context("Failed to hash bytes") 173 - } 174 - 175 - fn get_secret_key(path: PathBuf) -> Result<PrivateKey> { 176 - let (mut secret_key, _) = { 177 - let key_data = std::fs::read_to_string(path) 178 - .map(Zeroizing::new) 179 - .context("Failed to read secret key")?; 180 - 181 - PrivateKey::from_base64(&key_data[..]) 182 - .map_err(Error::new) 183 - .context("Failed to decode secret key")? 184 - }; 185 - 186 - if secret_key.is_encrypted() { 187 - let passphrase = rpassword::prompt_password("key passphrase: ") 188 - .map(Zeroizing::new) 189 - .context("Failed to read secret key password")?; 190 - 191 - secret_key 192 - .decrypt_with_password(&passphrase) 193 - .map_err(Error::new) 194 - .context("Failed to decrypt secret key")?; 195 - } 196 - 197 - Ok(secret_key) 198 - } 199 - 200 - fn get_public_key(path: PathBuf) -> Result<PublicKey> { 201 - let key_data = std::fs::read_to_string(path).context("Failed to read public key")?; 202 - 203 - let (public_key, _) = PublicKey::from_base64(&key_data[..]) 204 - .map_err(Error::new) 205 - .context("Failed to decode public key")?; 206 - 207 - Ok(public_key) 208 - } 209 - 210 - impl<E: fmt::Display> fmt::Display for Error<E> { 211 - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 212 - write!(f, "{}", self.inner) 213 - } 214 - } 215 - 216 - impl<E: fmt::Display + fmt::Debug> error::Error for Error<E> {} 217 - 218 - impl<E> Error<E> { 219 - fn new(inner: E) -> Self { 220 - Self { inner } 221 - } 222 - }
+75
src/utils.rs
··· 1 + //! Catch-all utilities module. 2 + 3 + use std::error; 4 + use std::fmt; 5 + use std::path::PathBuf; 6 + 7 + use anyhow::{Context, Result}; 8 + use git2::{ObjectType, Oid}; 9 + use libsignify::{Codeable, PrivateKey, PublicKey}; 10 + use zeroize::Zeroizing; 11 + 12 + /// An error type. 13 + #[derive(Debug)] 14 + pub struct Error<E> { 15 + inner: E, 16 + } 17 + 18 + impl<E: fmt::Display> fmt::Display for Error<E> { 19 + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 20 + write!(f, "{}", self.inner) 21 + } 22 + } 23 + 24 + impl<E: fmt::Display + fmt::Debug> error::Error for Error<E> {} 25 + 26 + impl<E> Error<E> { 27 + /// Create a new [`Error`]. 28 + pub fn new(inner: E) -> Self { 29 + Self { inner } 30 + } 31 + } 32 + 33 + /// Hash the provided bytearray and return the 34 + /// resulting checksum. 35 + #[inline] 36 + pub fn hash_bytes(bytes: &[u8]) -> Result<Oid> { 37 + Oid::hash_object(ObjectType::Blob, bytes).context("Failed to hash bytes") 38 + } 39 + 40 + /// Read a public key from the given path. 41 + pub fn get_public_key(path: PathBuf) -> Result<PublicKey> { 42 + let key_data = std::fs::read_to_string(path).context("Failed to read public key")?; 43 + 44 + let (public_key, _) = PublicKey::from_base64(&key_data[..]) 45 + .map_err(Error::new) 46 + .context("Failed to decode public key")?; 47 + 48 + Ok(public_key) 49 + } 50 + 51 + /// Read a secret key from the given path. 52 + pub fn get_secret_key(path: PathBuf) -> Result<PrivateKey> { 53 + let (mut secret_key, _) = { 54 + let key_data = std::fs::read_to_string(path) 55 + .map(Zeroizing::new) 56 + .context("Failed to read secret key")?; 57 + 58 + PrivateKey::from_base64(&key_data[..]) 59 + .map_err(Error::new) 60 + .context("Failed to decode secret key")? 61 + }; 62 + 63 + if secret_key.is_encrypted() { 64 + let passphrase = rpassword::prompt_password("key passphrase: ") 65 + .map(Zeroizing::new) 66 + .context("Failed to read secret key password")?; 67 + 68 + secret_key 69 + .decrypt_with_password(&passphrase) 70 + .map_err(Error::new) 71 + .context("Failed to decrypt secret key")?; 72 + } 73 + 74 + Ok(secret_key) 75 + }