···11+//! Return the fingerprint of some key.
22+33+use std::path::PathBuf;
44+55+use anyhow::Result;
66+77+use super::utils;
88+99+/// Execute the `fingerprint` command.
1010+pub fn command(key_path: PathBuf) -> Result<()> {
1111+ let public_key = utils::get_public_key(key_path)?;
1212+ let hash = utils::hash_bytes(public_key.key().as_ref())?;
1313+ println!("{hash}");
1414+ Ok(())
1515+}
+7-102
src/main.rs
···11+mod fingerprint;
22+mod sign;
13mod utils;
44+mod verify;
2536use std::path::PathBuf;
4755-use anyhow::{Context, Result};
88+use anyhow::Result;
69use clap::{Parser, Subcommand};
77-use git2::{Oid, Repository};
88-use libsignify::{Codeable, Signature};
9101011/// A git sub-command to sign arbitrary objects
1112#[derive(Parser)]
···5556 Action::Sign {
5657 secret_key,
5758 git_object_id: oid,
5858- } => sign(secret_key, oid),
5959+ } => sign::command(secret_key, oid),
5960 Action::Verify {
6061 public_key,
6162 print_signed_oid: recover,
6263 git_tree_oid: oid,
6363- } => verify(public_key, recover, oid),
6464- Action::Fingerprint { key } => fingerprint(key),
6464+ } => verify::command(public_key, recover, oid),
6565+ Action::Fingerprint { key } => fingerprint::command(key),
6566 }
6667}
6767-6868-fn verify(key_path: PathBuf, recover: bool, oid: String) -> Result<()> {
6969- let repo = Repository::open(".").context("Failed to open git repository")?;
7070-7171- let oid = repo
7272- .revparse_single(&oid)
7373- .context("Failed to look-up git tree oid")?
7474- .id();
7575- let tree = repo
7676- .find_tree(oid)
7777- .context("No tree object found for the given revision")?;
7878-7979- let object = tree
8080- .get_name("object")
8181- .context("Failed to look-up signed object in the tree")?
8282- .to_object(&repo)
8383- .context("The signed object could not be retrieved")?;
8484- let object = object
8585- .as_blob()
8686- .context("The signed object is not a blob")?;
8787- let dereferenced_obj = object.content();
8888-8989- let signature = {
9090- let signature = tree
9191- .get_name("signature")
9292- .context("Failed to look-up signature in the tree")?
9393- .to_object(&repo)
9494- .context("The signature object could not be retrieved")?;
9595- let signature = signature
9696- .as_blob()
9797- .context("The signature object is not a blob")?;
9898- Signature::from_bytes(signature.content())
9999- .map_err(utils::Error::new)
100100- .context("Failed to parse signature")?
101101- };
102102-103103- let public_key = utils::get_public_key(key_path)?;
104104-105105- public_key
106106- .verify(dereferenced_obj, &signature)
107107- .map_err(utils::Error::new)
108108- .context("Failed to verify signature")?;
109109-110110- if recover {
111111- let oid = Oid::from_bytes(dereferenced_obj).context("Failed to parse git object id")?;
112112- println!("{oid}");
113113- }
114114-115115- Ok(())
116116-}
117117-118118-fn sign(key_path: PathBuf, oid: String) -> Result<()> {
119119- let repo = Repository::open(".").context("Failed to open git repository")?;
120120-121121- let oid = repo
122122- .revparse_single(&oid)
123123- .context("Failed to look-up git object id")?
124124- .id();
125125-126126- let object_blob = repo
127127- .blob(oid.as_bytes())
128128- .context("Failed to write object id to the git store")?;
129129-130130- let secret_key = utils::get_secret_key(key_path)?;
131131- let signature = secret_key.sign(oid.as_bytes()).as_bytes();
132132- let signature_blob = repo
133133- .blob(&signature)
134134- .context("Failed to write signature to the object store")?;
135135-136136- let mut tree_builder = repo
137137- .treebuilder(None)
138138- .context("Failed to get a git tree object builder")?;
139139-140140- // TODO: insert a tree entry containing the version of this program
141141-142142- tree_builder
143143- .insert("object", object_blob, 0o100644)
144144- .context("Failed to write object to the tree")?;
145145- tree_builder
146146- .insert("signature", signature_blob, 0o100644)
147147- .context("Failed to write signature to the tree")?;
148148-149149- let tree_oid = tree_builder
150150- .write()
151151- .context("Failed to write tree to the object store")?;
152152-153153- println!("{tree_oid}");
154154- Ok(())
155155-}
156156-157157-fn fingerprint(key_path: PathBuf) -> Result<()> {
158158- let public_key = utils::get_public_key(key_path)?;
159159- let hash = utils::hash_bytes(public_key.key().as_ref())?;
160160- println!("{hash}");
161161- Ok(())
162162-}
+49
src/sign.rs
···11+//! Create signatures with [`libsignify`].
22+33+use std::path::PathBuf;
44+55+use anyhow::{Context, Result};
66+use git2::Repository;
77+use libsignify::Codeable;
88+99+use super::utils;
1010+1111+/// Execute the `sign` command.
1212+pub fn command(key_path: PathBuf, oid: String) -> Result<()> {
1313+ let repo = Repository::open(".").context("Failed to open git repository")?;
1414+1515+ let oid = repo
1616+ .revparse_single(&oid)
1717+ .context("Failed to look-up git object id")?
1818+ .id();
1919+2020+ let object_blob = repo
2121+ .blob(oid.as_bytes())
2222+ .context("Failed to write object id to the git store")?;
2323+2424+ let secret_key = utils::get_secret_key(key_path)?;
2525+ let signature = secret_key.sign(oid.as_bytes()).as_bytes();
2626+ let signature_blob = repo
2727+ .blob(&signature)
2828+ .context("Failed to write signature to the object store")?;
2929+3030+ let mut tree_builder = repo
3131+ .treebuilder(None)
3232+ .context("Failed to get a git tree object builder")?;
3333+3434+ // TODO: insert a tree entry containing the version of this program
3535+3636+ tree_builder
3737+ .insert("object", object_blob, 0o100644)
3838+ .context("Failed to write object to the tree")?;
3939+ tree_builder
4040+ .insert("signature", signature_blob, 0o100644)
4141+ .context("Failed to write signature to the tree")?;
4242+4343+ let tree_oid = tree_builder
4444+ .write()
4545+ .context("Failed to write tree to the object store")?;
4646+4747+ println!("{tree_oid}");
4848+ Ok(())
4949+}
+60
src/verify.rs
···11+//! Verify signatures with [`libsignify`].
22+33+use std::path::PathBuf;
44+55+use anyhow::{Context, Result};
66+use git2::{Oid, Repository};
77+use libsignify::{Codeable, Signature};
88+99+use super::utils;
1010+1111+/// Execute the `verify` command.
1212+pub fn command(key_path: PathBuf, recover: bool, oid: String) -> Result<()> {
1313+ let repo = Repository::open(".").context("Failed to open git repository")?;
1414+1515+ let oid = repo
1616+ .revparse_single(&oid)
1717+ .context("Failed to look-up git tree oid")?
1818+ .id();
1919+ let tree = repo
2020+ .find_tree(oid)
2121+ .context("No tree object found for the given revision")?;
2222+2323+ let object = tree
2424+ .get_name("object")
2525+ .context("Failed to look-up signed object in the tree")?
2626+ .to_object(&repo)
2727+ .context("The signed object could not be retrieved")?;
2828+ let object = object
2929+ .as_blob()
3030+ .context("The signed object is not a blob")?;
3131+ let dereferenced_obj = object.content();
3232+3333+ let signature = {
3434+ let signature = tree
3535+ .get_name("signature")
3636+ .context("Failed to look-up signature in the tree")?
3737+ .to_object(&repo)
3838+ .context("The signature object could not be retrieved")?;
3939+ let signature = signature
4040+ .as_blob()
4141+ .context("The signature object is not a blob")?;
4242+ Signature::from_bytes(signature.content())
4343+ .map_err(utils::Error::new)
4444+ .context("Failed to parse signature")?
4545+ };
4646+4747+ let public_key = utils::get_public_key(key_path)?;
4848+4949+ public_key
5050+ .verify(dereferenced_obj, &signature)
5151+ .map_err(utils::Error::new)
5252+ .context("Failed to verify signature")?;
5353+5454+ if recover {
5555+ let oid = Oid::from_bytes(dereferenced_obj).context("Failed to parse git object id")?;
5656+ println!("{oid}");
5757+ }
5858+5959+ Ok(())
6060+}