isaacs / github

Just a place to track issues and feature requests that I have for github
2.2k stars 129 forks source link

Revoked and expired GPG subkeys should keep have verified tag on old signature #1099

Open soullivaneuh opened 6 years ago

soullivaneuh commented 6 years ago

I'm not sure it's an issue or a bad manipulation from me, but I don't how to do it with another way.

In order to keep my master key secure and valid, I'm trying to do what is explain on this article.

I'll first explain what I did to test, step by step.

First, I create the main key with certificate role only (C).

GPG main key creation: ``` $ gpg --full-gen-key --expert gpg (GnuPG) 2.1.15; Copyright (C) 2016 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Please select what kind of key you want: (1) RSA and RSA (default) (2) DSA and Elgamal (3) DSA (sign only) (4) RSA (sign only) (7) DSA (set your own capabilities) (8) RSA (set your own capabilities) (9) ECC and ECC (10) ECC (sign only) (11) ECC (set your own capabilities) Your selection? 8 Possible actions for a RSA key: Sign Certify Encrypt Authenticate Current allowed actions: Sign Certify Encrypt (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? s Possible actions for a RSA key: Sign Certify Encrypt Authenticate Current allowed actions: Certify Encrypt (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? e Possible actions for a RSA key: Sign Certify Encrypt Authenticate Current allowed actions: Certify (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? q RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) Requested keysize is 2048 bits Please specify how long the key should be valid. 0 = key does not expire = key expires in n days w = key expires in n weeks m = key expires in n months y = key expires in n years Key is valid for? (0) Key does not expire at all Is this correct? (y/N) y GnuPG needs to construct a user ID to identify your key. Real name: Sullivan Senechal Email address: soullivaneuh@gmail.com Comment: You selected this USER-ID: "Sullivan Senechal " Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. gpg: key 2886875B5AF6449D marked as ultimately trusted gpg: revocation certificate stored as '/home/sullivan/.gnupg/openpgp-revocs.d/9E0BCC27843CF75E7604AFFD2886875B5AF6449D.rev' public and secret key created and signed. pub rsa2048 2017-10-21 [C] 9E0BCC27843CF75E7604AFFD2886875B5AF6449D uid Sullivan Senechal ```

Then, I add a signin (S) subkey.

GPG signing subkey creation: ``` $ gpg --edit-key 9E0BCC27843CF75E7604AFFD2886875B5AF6449D gpg (GnuPG) 2.1.15; Copyright (C) 2016 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Secret key is available. gpg: checking the trustdb gpg: marginals needed: 3 completes needed: 1 trust model: pgp gpg: depth: 0 valid: 3 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 3u sec rsa2048/2886875B5AF6449D created: 2017-10-21 expires: never usage: C trust: ultimate validity: ultimate [ultimate] (1). Sullivan Senechal gpg> addkey Please select what kind of key you want: (3) DSA (sign only) (4) RSA (sign only) (5) Elgamal (encrypt only) (6) RSA (encrypt only) Your selection? 4 RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) Requested keysize is 2048 bits Please specify how long the key should be valid. 0 = key does not expire = key expires in n days w = key expires in n weeks m = key expires in n months y = key expires in n years Key is valid for? (0) Key does not expire at all Is this correct? (y/N) y Really create? (y/N) y We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. sec rsa2048/2886875B5AF6449D created: 2017-10-21 expires: never usage: C trust: ultimate validity: ultimate ssb rsa2048/05A1185713266A40 created: 2017-10-21 expires: never usage: S [ultimate] (1). Sullivan Senechal gpg> save ```

Then I export all the part and secure my key by re-importing only the subkeys:

$ gpg -a --export 9E0BCC27843CF75E7604AFFD2886875B5AF6449D > key.pub
$ gpg -a --export-secret-keys 9E0BCC27843CF75E7604AFFD2886875B5AF6449D > key.priv
$ gpg -a --export-secret-subkeys 9E0BCC27843CF75E7604AFFD2886875B5AF6449D > sub.priv
$ ls -l
total 12
-rw-r--r-- 1 sullivan sullivan 3847 oct.  21 10:50 key.priv
-rw-r--r-- 1 sullivan sullivan 2082 oct.  21 10:50 key.pub
-rw-r--r-- 1 sullivan sullivan 2978 oct.  21 10:51 sub.priv
$ gpg --delete-secret-keys 9E0BCC27843CF75E7604AFFD2886875B5AF6449D
$ gpg --import sub.priv

Then I add the pub key here: https://github.com/settings/keys

image

I edit my .gitconfig to tell git to use my GPG key, with the main ID:

[user]
        name = Sullivan SENECHAL
        email = soullivaneuh@gmail.com
        signingkey = 9E0BCC27843CF75E7604AFFD2886875B5AF6449D

And I push a test commit, signed with the key. Yay! It's verified and signed with the subkey.

image

Well. Now imagine the fact my computer was stolen and my subkey is compromised. So I have to revoke it and create a new one. Let's go.

GPG subkey revokation and add: ``` $ gpg --import key.priv gpg: key 2886875B5AF6449D: "Sullivan Senechal " not changed gpg: key 2886875B5AF6449D: secret key imported gpg: Total number processed: 1 gpg: unchanged: 1 gpg: secret keys read: 1 gpg: secret keys unchanged: 1 $ gpg --edit-key 9E0BCC27843CF75E7604AFFD2886875B5AF6449D gpg (GnuPG) 2.1.15; Copyright (C) 2016 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Secret key is available. sec rsa2048/2886875B5AF6449D created: 2017-10-21 expires: never usage: C trust: ultimate validity: ultimate ssb rsa2048/05A1185713266A40 created: 2017-10-21 expires: never usage: S [ultimate] (1). Sullivan Senechal gpg> key 1 sec rsa2048/2886875B5AF6449D created: 2017-10-21 expires: never usage: C trust: ultimate validity: ultimate ssb* rsa2048/05A1185713266A40 created: 2017-10-21 expires: never usage: S [ultimate] (1). Sullivan Senechal gpg> revkey Do you really want to revoke this subkey? (y/N) y Please select the reason for the revocation: 0 = No reason specified 1 = Key has been compromised 2 = Key is superseded 3 = Key is no longer used Q = Cancel Your decision? 1 Enter an optional description; end it with an empty line: > Sigh. My PC was stolen. :-( > Reason for revocation: Key has been compromised Sigh. My PC was stolen. :-( Is this okay? (y/N) y sec rsa2048/2886875B5AF6449D created: 2017-10-21 expires: never usage: C trust: ultimate validity: ultimate The following key was revoked on 2017-10-21 by RSA key 2886875B5AF6449D Sullivan Senechal ssb rsa2048/05A1185713266A40 created: 2017-10-21 revoked: 2017-10-21 usage: S [ultimate] (1). Sullivan Senechal gpg> addkey Please select what kind of key you want: (3) DSA (sign only) (4) RSA (sign only) (5) Elgamal (encrypt only) (6) RSA (encrypt only) Your selection? 4 RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) Requested keysize is 2048 bits Please specify how long the key should be valid. 0 = key does not expire = key expires in n days w = key expires in n weeks m = key expires in n months y = key expires in n years Key is valid for? (0) Key does not expire at all Is this correct? (y/N) y Really create? (y/N) y We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. sec rsa2048/2886875B5AF6449D created: 2017-10-21 expires: never usage: C trust: ultimate validity: ultimate The following key was revoked on 2017-10-21 by RSA key 2886875B5AF6449D Sullivan Senechal ssb rsa2048/05A1185713266A40 created: 2017-10-21 revoked: 2017-10-21 usage: S ssb rsa2048/BAF63FC60659C512 created: 2017-10-21 expires: never usage: S [ultimate] (1). Sullivan Senechal gpg> save $ gpg -a --export 9E0BCC27843CF75E7604AFFD2886875B5AF6449D > key.pub $ gpg -a --export-secret-subkeys 9E0BCC27843CF75E7604AFFD2886875B5AF6449D > sub.priv $ gpg -a --export-secret-keys 9E0BCC27843CF75E7604AFFD2886875B5AF6449D > key.priv $ gpg --delete-secret-keys 9E0BCC27843CF75E7604AFFD2886875B5AF6449D $ gpg --import sub.priv ```

I now have my revoked key and my fancy new one.

I remove the old GPG key from my GitHub account and replace it by the new one:

image

And there is the issue. The old subkey is not here anymore and the old commit is not verified at all:

image

But, according to pgpdump, the concerned subkey is still here and marked as revoked with the accurate date and time.

Dump of the final GPG pubkey: ``` Old: Public Key Packet(tag 6)(269 bytes) Ver 4 - new Public key creation time - Sat Oct 21 10:43:12 CEST 2017 Pub alg - RSA Encrypt or Sign(pub 1) RSA n(2048 bits) - ... RSA e(17 bits) - ... Old: User ID Packet(tag 13)(42 bytes) User ID - Sullivan Senechal Old: Signature Packet(tag 2)(311 bytes) Ver 4 - new Sig type - Positive certification of a User ID and Public Key packet(0x13). Pub alg - RSA Encrypt or Sign(pub 1) Hash alg - SHA256(hash 8) Hashed Sub: signature creation time(sub 2)(4 bytes) Time - Sat Oct 21 10:43:12 CEST 2017 Hashed Sub: key flags(sub 27)(1 bytes) Flag - This key may be used to certify other keys Hashed Sub: preferred symmetric algorithms(sub 11)(4 bytes) Sym alg - AES with 256-bit key(sym 9) Sym alg - AES with 192-bit key(sym 8) Sym alg - AES with 128-bit key(sym 7) Sym alg - Triple-DES(sym 2) Hashed Sub: preferred hash algorithms(sub 21)(5 bytes) Hash alg - SHA256(hash 8) Hash alg - SHA384(hash 9) Hash alg - SHA512(hash 10) Hash alg - SHA224(hash 11) Hash alg - SHA1(hash 2) Hashed Sub: preferred compression algorithms(sub 22)(3 bytes) Comp alg - ZLIB (comp 2) Comp alg - BZip2(comp 3) Comp alg - ZIP (comp 1) Hashed Sub: features(sub 30)(1 bytes) Flag - Modification detection (packets 18 and 19) Hashed Sub: key server preferences(sub 23)(1 bytes) Flag - No-modify Sub: issuer key ID(sub 16)(8 bytes) Key ID - 0x2886875B5AF6449D Hash left 2 bytes - 59 4e RSA m^d mod n(2044 bits) - ... -> PKCS-1 Old: Public Subkey Packet(tag 14)(269 bytes) Ver 4 - new Public key creation time - Sat Oct 21 10:48:41 CEST 2017 Pub alg - RSA Encrypt or Sign(pub 1) RSA n(2048 bits) - ... RSA e(17 bits) - ... Old: Signature Packet(tag 2)(314 bytes) Ver 4 - new Sig type - Subkey revocation signature(0x28). Pub alg - RSA Encrypt or Sign(pub 1) Hash alg - SHA256(hash 8) Hashed Sub: signature creation time(sub 2)(4 bytes) Time - Sat Oct 21 11:08:34 CEST 2017 Hashed Sub: reason for revocation(sub 29)(28 bytes) Reason - Key material has been compromised Comment - Sigh. My PC was stolen. :-( Sub: issuer key ID(sub 16)(8 bytes) Key ID - 0x2886875B5AF6449D Hash left 2 bytes - 0a ab RSA m^d mod n(2047 bits) - ... -> PKCS-1 Old: Signature Packet(tag 2)(574 bytes) Ver 4 - new Sig type - Subkey Binding Signature(0x18). Pub alg - RSA Encrypt or Sign(pub 1) Hash alg - SHA256(hash 8) Hashed Sub: signature creation time(sub 2)(4 bytes) Time - Sat Oct 21 10:48:41 CEST 2017 Hashed Sub: key flags(sub 27)(1 bytes) Flag - This key may be used to sign data Sub: issuer key ID(sub 16)(8 bytes) Key ID - 0x2886875B5AF6449D Sub: embedded signature(sub 32)(284 bytes) Ver 4 - new Sig type - Primary Key Binding Signature(0x19). Pub alg - RSA Encrypt or Sign(pub 1) Hash alg - SHA256(hash 8) Hashed Sub: signature creation time(sub 2)(4 bytes) Time - Sat Oct 21 10:48:41 CEST 2017 Sub: issuer key ID(sub 16)(8 bytes) Key ID - 0x05A1185713266A40 Hash left 2 bytes - e4 2e RSA m^d mod n(2048 bits) - ... -> PKCS-1 Hash left 2 bytes - af c7 RSA m^d mod n(2045 bits) - ... -> PKCS-1 Old: Public Subkey Packet(tag 14)(269 bytes) Ver 4 - new Public key creation time - Sat Oct 21 11:08:38 CEST 2017 Pub alg - RSA Encrypt or Sign(pub 1) RSA n(2048 bits) - ... RSA e(17 bits) - ... Old: Signature Packet(tag 2)(574 bytes) Ver 4 - new Sig type - Subkey Binding Signature(0x18). Pub alg - RSA Encrypt or Sign(pub 1) Hash alg - SHA256(hash 8) Hashed Sub: signature creation time(sub 2)(4 bytes) Time - Sat Oct 21 11:08:38 CEST 2017 Hashed Sub: key flags(sub 27)(1 bytes) Flag - This key may be used to sign data Sub: issuer key ID(sub 16)(8 bytes) Key ID - 0x2886875B5AF6449D Sub: embedded signature(sub 32)(284 bytes) Ver 4 - new Sig type - Primary Key Binding Signature(0x19). Pub alg - RSA Encrypt or Sign(pub 1) Hash alg - SHA256(hash 8) Hashed Sub: signature creation time(sub 2)(4 bytes) Time - Sat Oct 21 11:08:38 CEST 2017 Sub: issuer key ID(sub 16)(8 bytes) Key ID - 0xBAF63FC60659C512 Hash left 2 bytes - dc d9 RSA m^d mod n(2048 bits) - ... -> PKCS-1 Hash left 2 bytes - 6f 5f RSA m^d mod n(2044 bits) - ... -> PKCS-1 ```

So, AFAIK, the commits and tags signed before the revocation date should stay with a verified status.

If not, what is the goal of making subkey if, in any case, all your commits and tags will be unverified as soon as the subkey is revoked? I don't get it. In this case, I'm sure lots of people are continuing using the key even if it is compromised. :pensive: :thinking:

BTW, I have another question related to this issue. I have a current GPG key signing my commit. It was created while I was a truly beginner and it use master keys. I would like to revoke it to no be able to use it at all but without losing my old tag and commit signature verification. Is that even possible?

Regards.

aaronwest commented 6 years ago

Great question. I'm walking this exact same process right now.. in terms of revoking a master gpg key in favor of using a new subkey.

I was referencing these docs which say:

Your previous commits and tags will show as verified, as long as the key meets all other verification requirements.

But, @Soullivaneuh experience seems to indicate otherwise. I suppose what I'll do for now, is leave the master gpg key on my GitHub account and just add the subkey. Once I understand better what is happening I'll look at removing the revoked master key.

aaronwest commented 6 years ago

I messed around with this some today and appear to have things working. I didn't revoke the master key, no need to really since it hasn't been compromised.

  1. create a new signing subkey using gpg2 --edit-key <master-key-id-short>
  2. export the public key, using the LONG key-id format and copy it to the clipboard on my Mac in one operation: gpg2 --armor --export <subkey-id-long> | pbcopy
  3. delete the existing gpg key from my GitHub settings
  4. upload the public key of the subkey into my GitHub settings
  5. create and push different test commits where .git/config has signingkey set to the old short key ID and the new subkey's short key ID

Between steps 3 and 4 I checked my old commits and they were marked as Unverified briefly. This changed to Verified once I executed step 4. When you click the Verified bit on a commit a dialog displays showing the long format GPG key ID used in the commit. While this has changed - it's now showing the long format of the new subkey I created versus the master key ID - both the old and new commits show as verified given the relationship between the keys.

soullivaneuh commented 6 years ago

@aaronwest I don't see any subkey revocation on you process. Am I wrong?

aaronwest commented 6 years ago

@Soullivaneuh correct, I did not revoke any subkeys. I was signing my Git commits with my master key and after making the outlined changes I'm signing commits with a subkey. So the subkey is new.

soullivaneuh commented 6 years ago

@aaronwest Yeah, but this is not relevant to my use case.

Try to revoke the subkey and add an another one for signing and then re-upload the GPG signature. You will see your older commit unsigned.

longhuynh95 commented 6 years ago

In another case: https://docs.gitlab.com/ce/user/project/repository/gpg_signed_commits/index.html#removing-a-gpg-key

longhuynh95 commented 6 years ago

I just deleted my gpg and all my out commits had been unverified

gzm55 commented 6 years ago

So, AFAIK, the commits and tags signed before the revocation date should stay with a verified status.

The problem is that timestamp and date are not easy provable. The attacker can use the compromised keys sign a commit with mocking author/commit/signing dates.

nhooyr commented 6 years ago

Maybe you need to add the master key to github?

nhooyr commented 6 years ago

Ah nvm, the master is included in the export.

nagromc commented 5 years ago

So, AFAIK, the commits and tags signed before the revocation date should stay with a verified status.

The problem is that timestamp and date are not easy provable. The attacker can use the compromised keys sign a commit with mocking author/commit/signing dates.

@gzm55 You are right. But git log --show-signature shows the commit has a good signature (underlined in white in the snapshot below). Okay, it's revoked, but still good.

image

GitHub shows nothing about the signature verification and the revocation of the key:

image

gzm55 commented 5 years ago

The problem is that timestamp and date are not easy provable. The attacker can use the compromised keys sign a commit with mocking author/commit/signing dates.

@gzm55 You are right. But git log --show-signature shows the commit has a good signature (underlined in white in the snapshot below). Okay, it's revoked, but still good.

image

GitHub shows nothing about the signature verification and the revocation of the key:

image

git log checks the signature on the fly with the updated keys, and give 'GOOD with WARNING', so the user should have to evaluate the risk himself. The result from github may be a cache before the revoking.

When using the git, we have more information to prove the timestamp of signature by the relationship between the commits. That is, if a commit C sign by key A has a descendant commit D with a really GOOD signature and the timestamp of that descendant is older than the revoked timestamp of A, then the commit C could be treated as GOOD, since C < D < revoking-A.

sanmai commented 5 years ago

Just for the record, this behavior is documented here:

If your signing key is revoked or expired, GitHub cannot verify your signatures. If your key is revoked, use the primary key or another key that is not revoked to sign your commits.

valera-rozuvan commented 3 years ago

The underlying issue is actually very interesting. Do old commits signed with a compromised (and revoked) key introduce an attack vector in a project? Started a discussion over at HN: https://news.ycombinator.com/item?id=25856812 . What should happen to code that is signed by a compromised key?

valera-rozuvan commented 3 years ago

@isaacs What is your stand on this issue?

totikom commented 3 years ago

GPG has a build in mechanism to manage this. When you revoke the subkey, you have to choose a reason for this action. Some of them explicitly state, that subkey has not been compromised. IMHO, subkeys, revoked in this way should remain verified. In contrast, keys, revoked due to leaks, should be displayed as unverified, of even show a warning that the subkey was compromised.

bacoboy commented 3 years ago

This can probably be argued until the end of time about validity of a key after it has been revoked.

The point of the original post, I believe, is that IF they key was valid at the time of the commit/signature, if it later expires you can't say that is is now invalid because it WAS perfectly valid. So time isn't being considered when showing the badge.

When you talk about a revoked key you have to say the signatures are no longer valid because there just isn't enough detail to know the timing and why. Was it compromised AFTER the commit/signature was made (in which case the signature should be valid)? Or was it BEFORE in which case it is clearly suspicious.

So really I think the handling of this needs to be split between how expired keys and revoked keys are handled. So how about this:

  1. if key is revoked UNVERIFIED or even REVOKED (in red)?
  2. if key is expired but not revoked AND signature time < key expiration time = VERIFIED else UNVERIFIED

I believe only that expired case is what causes people to do a double take at all in github -- it was valid and now it isn't? ¯\_(ツ)_/¯.

I'm not speaking to how GPG handles this in general at the command line. I'm sure if you posted over on the main project there would be no shortage of opinions. But here we are just talking about a UI treatment on GitHub.

brandonkal commented 3 years ago

GitHub should add an "Archive" option for old keys. Don't trust the key for new commits but keep the cached "verified" status on any existing commits.

It would make sense to mark any signature made with a revoked key as "REVOKED" That way if any fraudulent signatures were possible they can be marked as such.

But the nature of git is such that any new commit is a descendant of an older commit. So if you sign a new commit and it verifies you are vouching for the state of the repository then.

isaacs commented 3 years ago

But the nature of git is such that any new commit is a descendant of an older commit. So if you sign a new commit and it verifies you are vouching for the state of the repository then.

Yes, but given the nature of human trust etc, I might "vouch for" a state of the repository, because I trust my colleague who I believe has vouched for the state just prior to mine, and only later do we find out that it was a malicious use of my colleague's key.

There is a world of difference between "expired" and "revoked due to compromise".

It sounds like everyone pretty much agrees with the basic principle here though. If a key expires naturally, or is "archived" in some way to indicate that it was not known to be leaked or compromised, then commits made with that key during its valid time should continue to be treated as valid.

If a key is revoked as compromised, imo, the safest thing is to assume that it was always suspect, unless the time of compromise can be verified in some way. Perhaps the best solution here would be a way to archive keys, and indicate whether it was:

And when a key expires naturally, just move it into that third state.

brandonkal commented 3 years ago

There is a world of difference between "expired" and "revoked due to compromise".

Agreed. I wish git log --show-signature understood this. It highlights a commit in red regardless of if the subkey was since expired or compromised. So it would be nice to see GitHub providing a better user experience.

You can forge time though so I would say you could reduce the options to just compromised or not compromised (expired).

maxgoedjen commented 3 years ago

As a few people have pointed out over this thread, timestamps in commits can be basically arbitrarily set, but is there some way to mark commits that had been pushed (ie, that GitHub has seen) before expiration as "good but expired?" Imagine the overhead on keeping track of this would be non-negligible, but seems like a potential middle ground.

SimpleXtra commented 3 years ago

Hi all, I'm changing my GPG key because I'm pretty sure I lost my private key. But I'm still unsure whether removing my old GPG key on GitHub will make my previous commits became unverified, due to the vague words used in this documentation.

Is there any way to add my new GPG key while still maintaining the verification badge on my previous commits? Thanks.

RafikFarhad commented 3 years ago

@SimpleXtra If you delete your old GPG key from the github dashboard, all your previous commit will be shown Unverified. You can add your new GPG Public Key along side with the previous one, that will preserve the verification badge for your old commits.

SimpleXtra commented 3 years ago

@RafikFarhad thanks for the reply. However, I'm still wondering whether keeping my old GPG Public Key on GitHub would pose any security concerns. From what I've learned, if you lose access to your private key, you should somehow remove the public key or at least tell everyone who uses the public key that this particular key is no longer in use.

RafikFarhad commented 3 years ago

@SimpleXtra I was searching answer for the exact same question and I landed here. Unfortunately I did not find any answer for this question yet. I want to delete one of my GPG key from github account, but I am unsure about the status of my commits with that key. 🙁

bacoboy commented 3 years ago

@SimpleXtra the validity of a key has nothing to do with if it is on github or not. If I have a clone and pull your public key from the keyserver, the validity of it is based on 1) is it expired and 2) is it revoked. So removing an old/unused key from github does not make it valid or invalid - it simply associated the public key with your github userid. If you feel that your private key is compromised, then you should revoke that key saying "this is bad, don't trust".

The point of this issue centers more around a key the user feels is NOT compromised, but simply expired. Since commits in the past were valid when signed, and if the key has NOT been revoked as bad, then some feel that github should not flip from valid to invalid simply because time has passed. The tricky part here is that time in a git commit can be set to whatever you want (like the way phone spammers set the callerid to whatever they want). So if a key has expired and you push a commit signed with the expired key BUT the commit date is < expiration date, can that be trusted? Can github even tell the difference? This is the grey area that this thread is trying to figure out. Can an expired key still be trusted after expiration (assuming it isn't revoked)? I don't think anybody here knows enough of the internal workings of github to say if they can even tell between a commit signed and pushed prior to the expiration date or after.

Some have suggested an additional badge(s) for these cases since there are currently only 2 - valid and not valid. It seems like you need:

This thread will continue on and on forever while people debate how to bucket 5 things into 2 so let's just make 5 badges?

mpdude commented 3 years ago

~Is this also an issue if you register the GPG „master“ key on GitHub to confirm your identity, but then sign commits with subkeys that you later revoke?~

~To me it seems in the initial example, the identity added in GitHub was the subkey that was later revoked?~

In order to have a new subkey show as "verified", you need to gpg --export --armor [yourkeyid] and update GitHub account settings with this new key export. The key export contains the master key as well as all subkeys, newly added and revoked ones.

So, my initial assumption that you can register your public master key only, and that all commits signed with a subkey of it (however that link could be made...) will show as valid was wrong. You need to update your GPG settings in GitHub with an export containing the master and all subkeys, and expired or revoked subkeys will show as "unverified" just as the OP described.

mpdude commented 3 years ago

I just learned that git log has the %G? format placeholder to show GPG signature statuses. From the man page:

"G" for a good (valid) signature, "B" for a bad signature, "U" for a good signature with unknown validity, "X" for a good signature that has expired, "Y" for a good signature made by an expired key, "R" for a good signature made by a revoked key, "E" if the signature cannot be checked (e.g. missing key) and "N" for no signature.

valera-rozuvan commented 3 years ago

Do commits really have to be marked as unverified, when I remove my GPG key from my account? Even if the key remains valid, and not expired?

Felixoid commented 3 years ago

Just faced an issue, when my commits were marked as unverified. It's pretty confusing, since the setting state that they won't be.

It would be much better to have "expired" instead of "unverified"

snarkyerica commented 3 years ago

Faced this issue as well. I keep my primary key on a PGP Smartcard, and generate sign-only subkeys for machines I do a lot of development on. This introduces an issue in which all commits that I signed using a machine-specific subkey become unverified once I revoke the key due to no longer using that device. That's a problem since the underlying primary key is still valid, and all commits still have GOODSIG, just with a revoked subkey.