Page MenuHome GnuPG

Key expiration time ignored for zero creation date keys
Closed, ResolvedPublic

Description

GnuPG usually ignores the key expiration date when the key's creation date is set to zero (e.g. 1970-01-01) and treats the key as if it doesn't expire. For example, here is a key with such a date that expired June 2019:

-----BEGIN PGP PUBLIC KEY BLOCK-----

xjMEAAAAABYJKwYBBAHaRw8BAQdAKTUvEQJiYcC9ODhvNWkMfdCLPm8IjFgq9V08
6sPqFQXNB0V4YW1wbGXCZwQTFggAGQUCAAAAAAkQA3p8nXsU19ICGwMFCV2UTIAA
AKYRAP90FrOK7jPVldQSDbHRtKLieCBGwHxQybRntR7Rw19qIAD/WvzblYv9aU/R
Bm0Hxy2tlS8Sj60stKn24Ix1oc/yDAo=
=UBbd
-----END PGP PUBLIC KEY BLOCK-----

The --list-packets command shows the key expiration time subpacket corresponding to June 2019 (reminder: "expires 0" is only because this is a version 4 key packet):

$ gpg --list-packets example.asc
:public key packet:
        version 4, algo 22, created 0, expires 0
...
        hashed subpkt 9 len 4 (key expires after 49y170d13h20m)
...

However, with --show-key and for any uses of the key that I've tried, this expiration date is ignored. For example, here's a cleartext signed document with that key, example.txt:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

hello
-----BEGIN PGP SIGNATURE-----

wnUEARYIACcFAl1HYnUJEAN6fJ17FNfSFiEEF+GNHkxnebcbPb6lA3p8nXsU19IA
AAPqAP4ucCyrQnoexJanZMJGrKIXs9Y+b77+353ef3bECY2WXAD/YMOKkIb3CzTD
ort76CYkg/i8O2Y4qFcurD2p052QCAw=
=mZaN
-----END PGP SIGNATURE-----

The --verify command ignores that it has expired:

$ gpg --import example.asc 
gpg: key 037A7C9D7B14D7D2: public key "Example" imported
gpg: Total number processed: 1
gpg:               imported: 1

$ gpg --verify example.txt
gpg: Signature made Sun Aug  4 22:55:49 2019 UTC
gpg:                using EDDSA key 17E18D1E4C6779B71B3DBEA5037A7C9D7B14D7D2
gpg: Good signature from "Example" [uncertain]
Primary key fingerprint: 17E1 8D1E 4C67 79B7 1B3D  BEA5 037A 7C9D 7B14 D7D2

However, if I nudge the creation date forward by 1 second, leaving everything else the same (including the key material):

-----BEGIN PGP PUBLIC KEY BLOCK-----

xjMEAAAAARYJKwYBBAHaRw8BAQdAKTUvEQJiYcC9ODhvNWkMfdCLPm8IjFgq9V08
6sPqFQXNB0V4YW1wbGXCZwQTFggAGQUCAAAAAQkQSVb+epD++gcCGwMFCVz7tf8A
AIhsAQCptZtpe0Ue7wlhlzK5SM2QaXhfLHxU4b/42fta4MoBmQD6Aj9KJJXFzM3G
wLCZhzDMMUrr5cgptpdwQvGMOn2shg8=
=sWiM
-----END PGP PUBLIC KEY BLOCK-----

Suddenly GnuPG sees the expiration date:

gnupg/bin/gpg --show-key example1.asc 
pub   ed25519 1970-01-01 [SC] [expired: 2019-06-08]
      384B5CE1F3BD763810F0C97B4956FE7A90FEFA07
uid                      Example

Signed document using this key, :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

hello
-----BEGIN PGP SIGNATURE-----

wnUEARYIACcFAl1HZEoJEElW/nqQ/voHFiEEOEtc4fO9djgQ8Ml7SVb+epD++gcA
AF4kAQDku0vZiyKvp9+oLNtXhL9wP2zvF51jBAjVfgL+A/WgdAEA9l0z6qBjYEFq
eBsZSNB/xTefiqTsJ7qyBzoXQhm2pAU=
=Zvgz
-----END PGP SIGNATURE-----

And in GnuPG:

$ gpg --import example1.asc 
gpg: key 4956FE7A90FEFA07: public key "Example" imported
gpg: Total number processed: 1
gpg:               imported: 1

$ gpg --verify example1.txt
gpg: Signature made Sun Aug  4 23:03:38 2019 UTC
gpg:                using EDDSA key 384B5CE1F3BD763810F0C97B4956FE7A90FEFA07
gpg: Good signature from "Example" [expired]
gpg: Note: This key has expired!

As far as I can tell, this bug only affects keys with a creation date of zero, but I haven't checked thoroughly.

Details

Version
2.2.17

Event Timeline

werner triaged this task as Normal priority.Aug 5 2019, 10:00 AM
werner added a project: gnupg (gpg22).

I think that I located the cause of this bug:

diff --git a/g10/getkey.c b/g10/getkey.c
index 57617a0a9..b47b6c5e4 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -2753,7 +2753,9 @@ merge_selfsigs_main (ctrl_t ctrl, kbnode_t keyblock, int *r_revoked,
 	    {
 	      PKT_user_id *uid = k->pkt->pkt.user_id;
 
-	      if (uid->help_key_usage && uid->created > uiddate)
+	      if (uid->help_key_usage
+                  && (uid->created > uiddate
+                      || (uid->created == 0 && uiddate == 0)))
 		{
 		  key_usage = uid->help_key_usage;
 		  uiddate = uid->created;
@@ -2790,7 +2792,9 @@ merge_selfsigs_main (ctrl_t ctrl, kbnode_t keyblock, int *r_revoked,
 	  if (k->pkt->pkttype == PKT_USER_ID)
 	    {
 	      PKT_user_id *uid = k->pkt->pkt.user_id;
-	      if (uid->help_key_expire && uid->created > uiddate)
+	      if (uid->help_key_expire
+                  && (uid->created > uiddate
+                      || (uid->created == 0 && uiddate == 0)))
 		{
 		  key_expire = uid->help_key_expire;
 		  uiddate = uid->created;

... where we use 0 as exceptional value.

I checked the code and your patch looks right. I am going to apply it.

werner claimed this task.