Byron / gitoxide

An idiomatic, lean, fast & safe pure Rust implementation of Git

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support signed commits and tags

alexanderkjall opened this issue · comments

It would be great to have the ability to create commits that are signed, I thought that this issue might be a good place to start talking about how that workflow should be designed.

Here is a post that describes how the signing process works with git2-rs:

https://blog.hackeriet.no/signing-git-commits-in-rust/

Basically it creates a commit object in memory, lets the user program sign it however they want, and then have a function that writes the object together with the signature string to the git repository.

That design have a couple of pros:

  • no need for the library to interact with gpg, which can be tricky at best and a source of security holes at worst.
  • support for multiple different signing algorithms, it's the user that decides if it should be signed with gpg or s/mime.

But it also adds complexity for the user of the library, that need to do all the heavy lifting of interacting with gpg (or other). And have multiple different ways to create a commit.

One other point is that there now exists a pure-rust pgp implementation called https://sequoia-pgp.org/ that might be better to use than the gpgme library.

How would you like to design the library functions for creating signed commits?

In gitoxide, this would work similarly, and I believe it's possible to combine the best of both worlds.

  1. Create the commit object to your liking
  2. Serialize it to a buffer
  3. Sign the buffer content and add the signature to the corresponding extra header field. Usually this is gpgsig or gpgsig-256 for different hash functions or settings.

For generating the signature, which indeed can be quite involved, I believe it would be reasonable to provide the necessary infrastructure (behind a cargo feature toggle). Using sequoia would be great, I am all in for that, even though I can imagine providing a version with gpgme bindings as well (I have made good experiences with it).

Last but not least, please note that I have personal interest in this to work as well since I sign every one of my commits.

Step 1 through 3 could be handled by a function like this sign_commit(&mut owned::Commit, impl FnOnce(&[u8])->&BStr), whereas the FnOnce call signs the serialized version of the given Commit and returns the name of the header field to hold it.

gitoxide would provide typical signing functions like so a call could look like this: sign_commit(&mut commit, PGPSign::with_key("mykeyid"))? or sign_commit(&mut commit, |buf| pgp_sign(buf, Key::from("mykeyid")?))?.

And one step further down the road this would probably look more like this: commit.sign(PGPSignature::with_key("mykeyid")?)?. The latter fits more into what's currently there, for sure.

In case its of use, in gitext-rs/git2-ext#24, I did a port of git's signing logic to Rust/git2.

Thanks for sharing @epage! Having this should accelerate implementing signatures in gitoxide as well.

commented

is this planned in a future release, or are we still discussing options to implement it? Signing commits would be a great addition to goxide!

gitoxide has recently learned gix commit verify which does the opposite. It was (mostly) contributed and verification and signing are very much related: what's a signature worth if it's not verified? That's particularly true for testing such a feature.

With that said, I have no immediate plans on working on this as it's not required by cargo, which drives features right now.