GitoxideLabs / gitoxide

An idiomatic, lean, fast & safe pure Rust implementation of Git
Apache License 2.0
8.92k stars 304 forks source link

Support signed commits and tags #12

Open alexanderkjall opened 4 years ago

alexanderkjall commented 4 years ago

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:

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?

Byron commented 4 years ago

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.

epage commented 1 year ago

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

Byron commented 1 year ago

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

officialpiyush commented 1 year ago

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!

Byron commented 1 year ago

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.