Git files hidden in plain sight
tylercipriani.com
tylercipriani.com
Does this work differently with git?
The solution to using weak algorithms is to not use them, not to hide your public key. If you don’t reveal your public key, then there’s effectively no value in the signatures made by its private half.
But again: you don’t actually get authenticity if you obtain the public key from the same untrusted channel as the signed material. The key has to come from another channel (another simplification, but true in PGP and git’s case). That channel can be the user’s GitHub profile, website, etc., but it can’t be the repository itself.
curl https://github.com/${username}.keys
curl https://github.com/${username}.gpg | gpg --list-packets
Interestingly enough, since changing the GH keys is subject to GH authentication (possibly involving 2FA), the owner's key is kind of validated (by GH) so it _kind of_ makes GH a gpg key notary.Having `git log --show-signatures` validate _all_ signatures is then a matter of:
curl https://github.com/${username}.gpg | gpg --import
Now I kind of wish GH would sign such user pub keys _at the time they're added_ (thus at the time GH authentication is deemed valid), thus ensuring they've not been tampered with in between.With a bit of UI GH could present a UI for a user to validate another user's key, and sign that assertion (with a GH private key, not the user's of course) as well.
Of course it hinges on trusting GH, but GH already signs e.g UI borne merge commits on your behalf (via https://github.com/web-flow.gpg) so there's that.
Then next step would be for GH to host an actual key server to accept off-band signed keys containing a magic comment that bind the keys and sigs to GH usernames...
Insecure algorithms are a red herring here too. Either I know what algo you used and can interact with you, or I don’t.
Example of such an insecure algorithm that might be relevant here?
On the other hand, approximately nobody actually verifies git commit signatures, so it doesn’t matter all that much :-)
It is something of a security risk because there is no audit log for force pushes and anyone with force push access to that repo could update that tag at any time.
Also, because it is a lightweight tag, it is not itself signed so could potentially be man-in-the-middled.
That said, yes it is a public key and public keys are meant to be public. In many threat models this isn't a "huge deal". The issue, as often the case, with public keys is that you still need a chain of trust somehow defining if you should trust that public key. A public key that you get from the repo itself that anyone could force push an update to is possibly not one you should trust without additional verification channels involved.
$ git tag v1.2.3.4.5
$ cat .git/refs/tags/v1.2.3.4.5
ee48e70a829d1fa2da82f14787051ad8e7c45b71
But annotated tags are full git objects hashed and stored in the object database (one of four things that can be stored, alongside blobs, trees, and commits). An annotated tag can store a tag message and records the user that created it plus a timestamp. All the metadata in an annotated tag can be GPG-signed. It can also point to any type of object, which is the feature being "abused" here, where we have a tag (currently oid dd20f6ea5) that points to a blob (currently debb772bf) instead of a commit. Normally blobs are only used within trees which are pointed to by other trees or commits. $ git show-ref -d junio-gpg-pub
dd20f6ea53bf6828baba3e2f279bf633eaae6815 refs/tags/junio-gpg-pub
debb772bfc2bfedbfd5830dbe2c1c149dbf054e9 refs/tags/junio-gpg-pub^{}
$ git cat-file -t junio-gpg-pub # i.e. dd20f6ea5
tag
$ git cat-file -t junio-gpg-pub^{} # i.e. debb772bf
blob
Interestingly, it's perfectly legal to have chains of annotated tags (and lightweight tags) which eventually resolve to a non-reference object. This process is called unwrapping and needs to be done carefully to avoid circular or excessively long reference chains. It's a very common thing to get wrong in git implementations that handle the plumbing themselves.You can see the tag object itself including the message using `git cat-file -p junio-gpg-pub` and the key it points to with the command in the article.
[1] https://git-scm.com/book/en/v2/Git-Basics-Tagging#_creating_...
I don't know if that's true anymore, if only because the ongoing popularity of the Git Flow branching model; the `git-flow` tools use annotated tags by default for every command that creates a tag (e.g. releases).
If a thing is truly expired, then why have it fill-up the commit graph.
That said, a public key - even an expired one - may have value in keeping around: Verifying older historic releases.
Github shows the updated tag.
git pull --tags shows:
! [rejected] <tag> -> <tag> (would clobber existing tag)
git pull --tags --force updates the tag.> if you 'git fetch', git does not update tags? I would be pretty surprised
This is the comment you replied to:
> By default, most things assume that tags are immutable and won't check for updates to a tag.
You can use options to change from the default. I don't know what point you are now trying to make, but this conversation is getting very laborious.
ssh://git.kernel.org/pub/scm/git/git.git
You won’t see it in any repo, just that one. This is not an easter egg in the git binary, just a quirky way to transmit a signing pubkey via a non-tree git sidechannel within the git source repo.It's probably not a great idea to use or rely on non-standard refs in general because it may conflict with other tools or future git capabilities, even if there were a "standard UI for unknown refs".
Works really great -- the UI is not cluttered with thousands of rarely-used entries, but all the data is still backed up and usable witth git tools. Now if only github actions could support this...
Implementations should probably just ignore the expiry of a key used for signing when checking a signature...
Certificates have an expiration date because keys can be compromised, and cryptographic algorithms can become weak and be broken. The expiration date imposes a time limit for possible fraudulent use of the key.
When using certificates, it’s also the certificate that expires, not the key. A new certificate for the same key can be issued (certificate renewal).
Signing key expiration exists for the same reason certificate expiration exists: we create keys that are infeasible to discover with current methods, and create replacements as techniques advance. This encourages us to create stronger keys over time.
Had you failed to notice a key expiration from the 80s, you would assume the signature is valid - but most computing devices these days could have just generated the signature without the original key.
>Had you failed to notice a key expiration from the 80s, you would assume the signature is valid ...
If the algorithm is broken then the implementation should not support verification using that algorithm no matter the expiration date. An attacker can update the key's expiration date to whatever they want if the algorithm is broken.