Hacker News new | past | comments | ask | show | jobs | submit login
Signing Git commits with your SSH key (2021) (calebhearth.com)
201 points by jiripospisil on Sept 14, 2022 | hide | past | favorite | 85 comments



To summarize the comments in this thread so far...

* Signing your commits is a waste of time

* Signing your commits with SSH keys is bad because it conflates an ephemeral key with a permanent identity

* Signing your commits with anything but GPG isn't worth it

The first point is hard to argue against because the commenters who offered the opinion didn't give many details to understand their perspective.

The second, which is the most common sentiment so far, seems to be because people misunderstand that it doesn't have to be your push/pull key. It can be any SSH key, including a special-purpose key whose only job is to be held securely and act as a signing key.

And the third kind of suffers the same problem as the first -- not enough details are given to understand.


My problems with git commit signing mostly overlap with the critiques leveled against GPG. That said, git’s implementation of signed commits combined with Github/Gitlab’s validation framework of only respecting the current key on a user’s profile really makes commit signing’s usefulness limited.

The signatures are stored within the commit object and the only way to resign a commit is to rewrite history. Also you can only attach one signature to a commit, though this is less of an issue.

GPG has plenty of critiques that I do agree with: horrible defaults, difficulty of use, a key model that is outdated and does not serve the plethora of uses it’s now used for, etc.

All of this adds up, tbh, that ephemeral keys are probably no worse than a GPG key. If your GPG key is compromised (or lost), you won’t be resigning your entire git history with your new key. You will simply note somewhere visible that X key was valid until Y date and Z key is the current valid key. Any commits pushed after Y date with X key are suspect.

The point being, signed git commits regardless of what type of key you use really only validate that a particular person at a particular instant in time signed that commit.

If anything, using a more ephemeral and disposable key will encourage Github/Gitlab/etc. to start thinking about key rotation on user profiles. As it stands, if you change your GPG key in Github all commits made with your previous key become invalid until you change you GPG key back. The fact you can change your key back is probably also bad.

The current state of git commit signing is useful, but that usefulness rapidly decays as the commit ages.


If the key is only used for signing, then why an SSH key?


because the ssh-keygen UI is considerably easier and likely more familiar than gpg.

I shouldn't have to know what ElGamel is to sign a commit.


> I shouldn't have to know what ElGamel is to sign a commit.

I use gpg to sign my commits, it was as easy to setup as git ssh keys were... I don't know what ElGamel is either.


I have a pretty decent security setup (password manager, multiple SSH identities, OTP 2FA, Yubikeys) but GPG is such a usability nightmare I don't want to touch it with a 10 foot pole.


That still doesn't answer why this needs to be solved by added SSH signing format to git (which everything in the ecosystem needs to adapt to) instead of creating a better gpg-keygen.


This seems to me a fundamentally bad idea: signing commits should be a "long lived" thing, but using an infrastructure designed for easily replaceable authentication (ie: add your pub keys to servers and remove/replace/destroy them at the very minimal suspicion of the private keys being compromised). And all the non-existing certification infrastructure (the article proposes one; we can end up with multiple incompatible signing/certification systems, none of them with the reach of existing OpenPGP). And at last, but not least, putting too many eggs in the same basket.


It’s better than not signing at all, though, which appears to be the current status quo.

You can also sign with a different key than your “regular” ssh key(s), and as such reduce the chance you’ll have to replace them.

Having said that, key rotation and distribution is obviously better with GPG, and I personally have been using that for years.


Commit signing with S/MIME also works great. The downside is that you have to buy an "email" S/MIME cert from one of the usual cert gatekeepers for a couple dollars, but in return anyone can verify the signatures without exchanging public keys with me (or building a web of trust), and expiration and revocation are solved problems (including verifying signatures made with keys that are now expired, which seems not really supported with SSH keys)


You may want to check out https://github.com/sigstore/gitsign! You can generate ephemeral x509 code signing certs for free using Sigstore.

(disclosure: I'm a maintainer for gitsign)


Wow! This looks like an incredible ecosystem for managing signatures and for verifying the software artifact supply chain.


How is expiration a solved problem? You won't be able to verify commits after the cert expired without additional information because you don't know that the commit timestamp is valid. For code signing you there are timestamping services to solve this but this means that you are now dependent on a central authority which could just host verified hashes without all the crypto mess.


You don't have to reuse your keys. You can have a separate key(s) for signing.


The only reason the article gives for using this over using the signing with GPG keys is that you will have an SSH key already. If you need to create a new key, are there any reasons for going for an SSH key over a GPG key?


Because you are already acustomed to ssh?

I personaly use GPG. However, GPG looks complex and the ergonomics of GnuPG cli is horrible.


So use some GUI?

CLI ergonomic around working with ssh keys and ssh certificates is not great either.

And GPG/PGP at least has some standards around key distribution, web of trust, subkeys, etc.


I use GPG Suite on Mac and even then the ergonomics are confusing. GPG/PGP is just kind of confusing for us not deeply into cryptography.


I looked up the screenshots. The app looks like the most trivial possible UI for basic public key cryptography. Just a basic list of your/other people's keys (pretty much a contact list) and some ways to acquire them.

SSH keys if used in place of GPG would have almost the same UI. It's not the problem of GPG, but of the underlying concepts.

You don't need to be deep into cryptography, just understand some basic concepts from the wikipedia article, or whatnot.


The real reason is: I don't gain any security from signing my own commits, I gain security when other people sign their commits which they are currently not doing.

Therefore, making things easier to set up makes a greater contribution to security than strict, gold-standard security features that nobody adopts.


You don't gain any security if you can't verify the signatures of the others.


Signing with a separate hardware-stored SSH key on a dongle (e.g.: Yubikey/FIDO2) will allow you to have a long-lived key without the risk of compromise.


If you're using a dongle, I expect you'd have your other SSH keys there as well. Is there a security benefit to using a separate SSH key if they all live on the same dongle? I'm having trouble thinking through that. Although, certainly the hardware dongle has security benefits over SSH keys on disk.


Yes -- you can separate identities if you want, and rotating keys means changing a lot less places, so you can compartmentalize your processes.


I can ssh (of course) with my ssh key, and now I can sign Git commits with it. Can I also use an ssh key for encryption? My keys are all ed25519 if that helps. I see a few proofs of concept on the web, but nothing as easy* as gpg.

My only use case for gpg asymmetric encryption is encrypting my offsite backups, and various small things. In other words, I encrypt only to myself, and I like asymmetric encryption because I can keep the private key offline.

*that word is used ironically. gnupg is the devil I know, so I don't mind it much these days, but I'd love to migrate off it completely.


Yes, this is incredibly easy to use: https://github.com/FiloSottile/age


Ah, I'd forgotten that age can use SSH keys. Thanks!


Gnupg is shit but PGP itself is just fine and we recently have more modern and well tested implementations of it now like https://sequoia-pgp.org/


Yeah, I'll certainly follow recomendation from someone who starts it with calling a well known successful FOSS project "shit". /s


Dodge K-cars were well known and succesful. They were also utter shit. Plenty of FOSS projects are of low quality but get adopted because they fulfil a need. Some dont age well. Some have poor docs. Some have insufferable interfaces. It's ok to call them shit. All code is shit anyway. Its just the smell ratio that varies.


Yeah, sequoia certainly doesn't shine here either, unless you call a dump of sq https://docs.sequoia-pgp.org/sq/ help screens a useful user facing documentation.

I guess it's a nice library, but it's no replacement for GnuPG. At least GnuPG has an actual user guide, FAQ, etc. with important concepts explained step by step.

As a GnuPG user, it would not be hard to switch for simplistic use cases without any specialized HW, I guess. I already know most of the concepts, but for new users,... I wish them luck with sq, lol. Documentation is pretty much nonexistent, and the web page for sq tool just links to library documentation.

Rust codebase is not everything.


It is a giant aging and super buggy C codebase. I found a serious CVE in it myself on accident any basic test suite would have caught.

It was very successful but it is nowhere near the security, documentation, testing, or UX standards of what we would call quality software today.


Looks like a typical GNU style C codebase with a few CVEs over the years.

https://ubuntu.com/security/cves?q=&package=gnupg

Not sure what's the grumbling about UX. Common tasks signing/verifying/encrypting are simple. Key export/import is also straightforward. So for common tasks you learn a few (~6) CLI --options by osmosis.

Web of trust/key management stuff is mostly done via interactive UI where you're prompted for what's needed after you invoke some action. Not too bad I guess. Certainly easier to be prompted for what's needed than remembering a ton of random CLI options or fishing through manpages, for tasks that you'll do very infrequently.


Yes. GNU C codebases are not written defensively or with strong test suites (if any) and tend to have piles of serious bugs that take years to spot. I use such tools heavily on a personal basis but I avoid running such things in production I high risk environments at almost all costs.

I also thought the same and argued the same about UX until I had to train several large teams to use it, and found myself making piles of shell script wrappers to pacify the majority of modern devs who are intimidated by any CLI commands that do not start with npm or git.

PGP is the right spec, IMO. It is just time to shift to more mature implementations that are easier to trust the defaults of and program against.

The majority of Sequoia devs are former GnuPG devs btw. They realized the shortest path to a broadly library-first testable codebase, a memory safety, secure default ciphers, etc was starting over.


Wow, it seems promising. Did you have a chance to use their CLI? Is it indeed better (more intuitive, less complex, more idiot-proof) than the GnuPG one?


The sq program is not stable yet. right?


No, but it is way more tested and stable than GnuPG imo. That said limited smartcard support keeps me from using it yet, but that is in testing and rapidly maturing.


ssh keys are keys. You can use them with openssl for encryption/decryption. It's a little bit more complicated than gpg but nothing an alias can't fix.


I tried to replace gpg with this setup last year and failed because I wanted to use FIDO2 ssh keys which are stored on a yubikey. It didn't work back then. My hope was that I could get to a setup where I only need a yubikey and the gitconfig to make this work. I stayed with gpg signing for now since my key is on the same yubikey as the ssh key now. Does this work now?

On that note I really like the FIDO ssh feature but would like to see more services support these. Arch User Repository still doesn't support these and I don't know what the status over at gitlab is now.


I sign commits with a pgp key on a yubikey and also use it for ssh. Check out gpg-agent. It works!


This is not what I meant. I used this setup before. But you need gpg, the right config, the ssh-agent from gpg etc. I did a setup like this on macOS, Linux, and windows. It was a nightmare to setup. MacOS starts an ssh-agent by default so one needs to rewrite the environment etc to inject gpg ssh-agent. Linux is a little simpler though.

What I wanted is to use the external ssh keys on a Fido key [1] in combination with the commit signing feature. With that I would skip the whole gpg part of the setup and only configure git and maybe ssh. But the generated keys (they have a -sk postfix) didn’t work with the signing feature.

https://fido.ftsafe.com/open-ssh-with-fido-keys/


And don’t get me started on windows and WSL. WSL has no access to USB. And there are no device pipes only file pipes. There is a solution for this with a custom process on windows which passes the Fido key over a file pipe/socket (not sure about the specifics anymore). There was no on click setup at the time when I did this. Maybe that has changed.


This works now, as of OpenSSH 8.9, even on Windows. I have this setup on Windows 11 + YubiKey 5C NFC + an SSH key. Signing pulls up the Windows Hello/FIDO2 PIN prompt and all.


Cool thanks! Will test that out then.


Don't think I am the use case here.

I have zero hesitancy to blow away a git ssh key for any reason and use different keys from different hosts which are not used for anything else.

Entangling an ephemeral key as a supposedly permanent signature would have to be for things I had no long term commitment to.


> I have zero hesitancy to blow away a git ssh key for any reason and use different keys from different hosts which are not used for anything else.

I'm a little confused. I thought this was how you're supposed to do it, so you can easily revoke access for a particular host.


Generally yes, but here you're using this ostensibly ephemeral key as an identity. Usually you want your identity to _not_ be ephemeral, so that it can reliably identify you.

Which is why this is a bit silly and I don't see why you'd do this rather than "good old" PGP.


I can setup a pair of SSH keys. I have given up trying to setup PGP. So that's one reason to not use ""good old" PGP".

Why can a PGP key be permanent but an SSH key not? I'm assuming both are just files and as a user you are required not to lose/give them away.


Lots of people use permanent-ish HSM-backed keys (like yubikeys) for SSH access so I guess this saves them from distributing another key? Outside of that I agree, I don't really see the point.


Mostly because using pgp (or more specifically gpg) is a pain in the ass and ssh-keygen is not


I think you should be signing with a different key than your push/pull key. It's just so you don't have to use GPG when key signing is required.


This is nice. At my company, some “bad actors” were pushing commits to git repositories that impersonated a bunch of employees at the company to repos that were essentially targeted hate crimes. I definitely recommend something like this.


Note that signing commits doesn't bar bad actors from pushing unsigned commits with forged identities.

Also note that until you can individually get the good actors' public key you can't verify their commits. So it's not enough to distribute the instructions in this webpage, you also have to have a trusted key exchange. Everyone who wants to verify commits will need a copy of everyone who might sign commits' public keys.

If you trust github then you can use them as a key broker like the "User SSH Keys from GitHub" section suggests, if all of your committers are github users.


> Note that signing commits doesn't bar bad actors from pushing unsigned commits with forged identities.

This would need to be coupled with a "reject unsigned commits" policy on push. For example - https://docs.gitlab.com/ee/user/project/repository/push_rule...

And note that the caveats that it has would require the person to log in to gitlab to not need to push (by using the webIDE instead) which leaves an audit trail there.

Similar functionality can be crafted with a pre-receive commit hook - https://docs.github.com/en/enterprise-server@3.2/admin/polic...

An example of such a hook - https://github.com/github/platform-samples/blob/master/pre-r...


> If you trust github then you can use them as a key broker like the "User SSH Keys from GitHub" section suggests, if all of your committers are github users.

Additionally you can enable "Vigilant Mode" to make it obvious when commits are untrusted.

https://github.blog/changelog/2021-04-28-flag-unsigned-commi...


Commits such as?


    commit 3c2f202543b31e9d7e2fff92a211a0f37ebcca9b (HEAD -> master)
    Author: Dave <dave@meanco.com>
    Date:   Tue Sep 13 21:32:41 2022 -0500

        I am not smart.


Just code contributions to some trans hating repo or something, don’t remember the details.



Please just use pgp.

You need expiration, permissible purpose, revocation, identity, etc embedded into a ‘key’.

Pgp is really really good at doing these things and has been though the ringer on security. Yes pgp sucks at its original Purpose (encrypting email) but it’s excellent for signing things.


Is there a particular implementation of PGP that folks should use?


GPG is available nearly everywhere on every platform. If you're on OSX you can install MacGpg which provides a nice UI.


if you sign your commits, you should also consider timestamping your commits. I use OpenTimestamps for this. Docs and some rationale here: https://github.com/opentimestamps/opentimestamps-client/blob...

from the doc:

> My signing keys (e.g. blog or Qubes code signing keys) do not have expiration dates. This is not laziness. There is a fundamental problem with using an expiration date on keys used for code signing (e.g. git tag -s), because it is unclear what the outcome should be when one verifies some old code (written and signed when the key was still valid) in the future when the key has already expired?

> Naturally we would like the old code, written and signed when the key was still valid, to continue to verify fine also in the future, after the key expires (and the developer passed away, perhaps). However, it is very problematic to prevent the attacker from creating falsified code pretending to be an old one.


Alright I'll bite - why do all this blockchain hoopla instead of just using SMIME/CMS's trusted timestamp feature? That already works fine with git signatures.


Personally I'm pretty against bitcoin et all for their wastefulness (PoW) or lack of improvement on existing systems (PoS), but I can definitely see trusted timestamps as a valid use of a public ledger. Ironically, since git is implemented as a merkle tree, you could do this quite easily in git as a "blockchain" minus the Proof of *. So, no distributed trust, but I'm personally usually glad to trade a little bit of centralization for a whole lot of performance/efficiency.


We are on the same page. I do think there are some gains, although I question the use of "permissionless" blockchains (we have to remember to add this caveat now since we decided 90s tech should now be called "permissioned blockchains"). A simple published ledger ("immutable append-only", like CT logs) seems like a much easier route. If nodes care enough, they can poll it and alert when the tip changes in a way that should not be allowed.


I believe GitHub's smimesign can include RFC3161 timestamps:

How to specify a timestamp server

https://github.com/github/smimesign/issues/47


Yep, precisely what I was referring to.


Can a non-PoW timestamp server actually be trusted? The thing with open timestamp etc is that it's completely trustless


"trustless" is not the word here... you are trusting the economic incentives of the blockchain system to remain in-tact. But I do agree with you that one could feasibly trust it "more" than a single entity protecting a key and acting correctly. However in practice "more" comes with a very very hefty price tag, in my experience one that makes it completely impractical in the real world. Look at the verification requirements:

- run a full bitcoin node, download the full blockchain - wait several hours after the timestamp is produced for the system to publish to blockchain (which also reduces the granularity of the timestamp, within this window the system is only "as secure" as a solution trusting a single entity) - download all the commits in the Merkle tree that was signed and published, and search for the commit you are verifying within the tree

Security in practice is about tradeoffs, and I can't imagine a scenario wherein these tradeoffs would work for me without ultimately having a centralized provider verify them for me, at which point I just have complexity with no gain over the traditional trusted timestamps.


Yes, because it's very small list of companies that have trusted timestamp servers and follow a strict set of rules re: key storage, rotation, issuance, etc.


TBH this is a good argument not to trust timestamp servers. AFAIK usually you just want to stick to one, and not treat a group of them interchangeably (ala the Internet Root Bundle). In any case, the owners of the repo (or email message) would decide for themselves which one(s) they want to trust.


We do use just a specific one at work. My point was that it's a highly secured process limited to just a few companies, and becoming one is a lot of effort, if at all possible. There are even some RFC3161 servers just not trusted by Windows, ergo: useless for most timestamping uses.


As much as you can trust SSL certificates and code-signing certificates.


Signing will say who signed it, but it cannot say when they signed it.


is it just me or is the opentimestamp thing poorly described in that after reading the how it works section I still have no idea wtf this thing is doing?

bitcoin.

merkle tree.

and some third party calendar server.

It's fine maybe this thing is so complicated that I'm not allowed to understand it. And if it's so complicated that it can't even be explained in a high level way, I don't want to use it.


Nice, if you have a distributed project.

If you work in a commercial environment with an authenticated central repository then all actions are logged. This is the best place to audit who-did-what.

I suppose this doesn’t work though if you have developers with legitimate reasons to push commits by other people. What would those be? Cherry picking bug fixes to a release branch? One engineer merging a branch where they’ve been collaborating with someone else? I would probably want to take ownership of the former, and the latter isn’t very common now in the era of “everything on master”.


I find that requiring signed git commits is extremely useful for metric-chasing github repo owners who can use it to justify claiming credit for bugfixes that I submitted but did not sign.


Signing Git commits with your SSH key, and other pointless things you can waste your time on.


SSH is a secure shell protocol. You should rotate your keys as much as possible. Why using it outside its context?

I use an ed25519 GPG key secured in a hardware security key. It’s convenient and secure. My SSH keys are ephemeral as much as possible.


You dont have to use the same ssh key you use to connect to a server. A ssh key can be created for just any purpose.


Public key cryptography is used in many applications. What’s the motivation for using encryption tools in a transport protocol for signing data or documents? It’s not a full solution, and makes the SSH code base larger, and harder to maintain.

GPG has key management tools and various functionalities around signing. Minisign is another clean tool to watch for.



I love this, GPG has always been really foreign to me. I still got the hang of it to verify my commits on github.


Thankfully, an alternative PGP implementation is quickly gaining traction: https://sequoia-pgp.org/




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: