Extending GPG Expiry

If you followed my last article on this subject, you have a GPG setup without the master private key on your computer. You also put an expiration date on that key. When your key expires, it can no longer be used to encrypt data for you. It can however still decrypt messages from prior to the expiry date. This does not help in the situation where your private key is compromised. In that case, all is lost and you should just start building a reputation again with another key.

This situation arises where you have been secure for 2 years, and your keys are about to expire. It stands to reason that you could expire your subkeys and make new ones with new expiration dates. That would probably be the most secure.

Failing that, I will document the easy way of loading up your private key and modifying the expiration dates so you can just continue using your whole setup. This is probably the most helpful way to get all this done, however a complete key-rotation every few years is never a bad idea.

Background

> gpg -K
/Users/admin/.gnupg/pubring.kbx
-------------------------------
sec#  rsa4096/5BB58AFFDF8ED9D6 2018-12-19 [C] [expires: 2020-12-18]
      Key fingerprint = 1FD5 D4A1 F326 8A90 9A5C  BFC7 5BB5 8AFF DF8E D9D6
uid                 [ultimate] Nikhil Nygaard <[email protected]>
uid                 [ultimate] Nikhil Nygaard <[email protected]>
ssb   rsa4096/1C434F4FBB0FE8B5 2018-12-19 [E] [expires: 2020-12-18]
ssb   rsa4096/6012253B4117B6DF 2018-12-19 [S] [expires: 2020-12-18]
ssb   rsa4096/641EAE1AB4833D26 2018-12-19 [A] [expires: 2020-12-18]

Notice the sec# up there for the [C] key. This means that your private key for the [C]ertify function is not available (because you explicitly removed it). If we try to edit the expiry times on that key or subkeys now, we will get errors:

> gpg --edit-key 5BB58AFFDF8ED9D6
gpg (GnuPG) 2.2.17; Copyright (C) 2019 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 subkeys are available.

pub  rsa4096/5BB58AFFDF8ED9D6
     created: 2018-12-19  expires: 2020-12-18  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/1C434F4FBB0FE8B5
     created: 2018-12-19  expires: 2020-12-18  usage: E
ssb  rsa4096/6012253B4117B6DF
     created: 2018-12-19  expires: 2020-12-18  usage: S
ssb  rsa4096/641EAE1AB4833D26
     created: 2018-12-19  expires: 2020-12-18  usage: A
[ultimate] (1). Nikhil Nygaard <[email protected]>
[ultimate] (2)  Nikhil Nygaard <[email protected]>

gpg> expire
Changing expiration time for the primary key.
gpg: WARNING: no user ID has been marked as primary.  This command may
              cause a different user ID to become the assumed primary.
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 2y
Key expires at Thu Sep  9 08:38:10 2021 PDT
Is this correct? (y/N) y
gpg: signing failed: No secret key
gpg: make_keysig_packet failed: No secret key

You can see that gpg tells us pretty clearly that we can't do that because we don't have the private key.

Before we continue, you should export your public key. This isn't necessary, but it is fun to see that it will be the only thing that changes in this process.

gpg --armor --export 5BB58AFFDF8ED9D6 > old.pub && cat old.pub
-----BEGIN PGP PUBLIC KEY BLOCK-----

[magic garbage]
-----END PGP PUBLIC KEY BLOCK-----

Procedure

You have to go find your private key and import it.

> gpg --import ~/Desktop/Security/Master/gpg/5BB58AFFDF8ED9D6.sec.asc
gpg: key 5BB58AFFDF8ED9D6: "Nikhil Nygaard <[email protected]>" not changed
gpg: key 5BB58AFFDF8ED9D6: secret key imported
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1
gpg:  secret keys unchanged: 1

Here is a before and after so you can see what should have changed. Namely #.

Before:

> gpg -K
/Users/admin/.gnupg/pubring.kbx
-------------------------------
sec#  rsa4096/5BB58AFFDF8ED9D6 2018-12-19 [C] [expires: 2020-12-18]
      Key fingerprint = 1FD5 D4A1 F326 8A90 9A5C  BFC7 5BB5 8AFF DF8E D9D6
uid                 [ultimate] Nikhil Nygaard <[email protected]>
uid                 [ultimate] Nikhil Nygaard <[email protected]>
ssb   rsa4096/1C434F4FBB0FE8B5 2018-12-19 [E] [expires: 2020-12-18]
ssb   rsa4096/6012253B4117B6DF 2018-12-19 [S] [expires: 2020-12-18]
ssb   rsa4096/641EAE1AB4833D26 2018-12-19 [A] [expires: 2020-12-18]

After:

> gpg -K
/Users/admin/.gnupg/pubring.kbx
-------------------------------
sec   rsa4096/5BB58AFFDF8ED9D6 2018-12-19 [C] [expires: 2020-12-18]
      Key fingerprint = 1FD5 D4A1 F326 8A90 9A5C  BFC7 5BB5 8AFF DF8E D9D6
uid                 [ultimate] Nikhil Nygaard <[email protected]>
uid                 [ultimate] Nikhil Nygaard <[email protected]>
ssb   rsa4096/1C434F4FBB0FE8B5 2018-12-19 [E] [expires: 2020-12-18]
ssb   rsa4096/6012253B4117B6DF 2018-12-19 [S] [expires: 2020-12-18]
ssb   rsa4096/641EAE1AB4833D26 2018-12-19 [A] [expires: 2020-12-18]

You will be prompted to enter the passcode for that private key, so make sure that you are you.

No we have the ability to edit the expiry value on the primary key.

gpg --edit-key 5BB58AFFDF8ED9D6
gpg (GnuPG) 2.2.17; Copyright (C) 2019 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  rsa4096/5BB58AFFDF8ED9D6
     created: 2018-12-19  expires: 2020-12-18  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/1C434F4FBB0FE8B5
     created: 2018-12-19  expires: 2020-12-18  usage: E
ssb  rsa4096/6012253B4117B6DF
     created: 2018-12-19  expires: 2020-12-18  usage: S
ssb  rsa4096/641EAE1AB4833D26
     created: 2018-12-19  expires: 2020-12-18  usage: A
[ultimate] (1). Nikhil Nygaard <[email protected]>
[ultimate] (2)  Nikhil Nygaard <[email protected]>

gpg> expire
Changing expiration time for the primary key.
gpg: WARNING: no user ID has been marked as primary.  This command may
              cause a different user ID to become the assumed primary.
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 2y
Key expires at Thu Sep  9 08:45:00 2021 PDT
Is this correct? (y/N) y

sec  rsa4096/5BB58AFFDF8ED9D6
     created: 2018-12-19  expires: 2021-09-09  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/1C434F4FBB0FE8B5
     created: 2018-12-19  expires: 2020-12-18  usage: E
ssb  rsa4096/6012253B4117B6DF
     created: 2018-12-19  expires: 2020-12-18  usage: S
ssb  rsa4096/641EAE1AB4833D26
     created: 2018-12-19  expires: 2020-12-18  usage: A
[ultimate] (1)  Nikhil Nygaard <[email protected]>
[ultimate] (2). Nikhil Nygaard <[email protected]>

Now you'll want to update the subkeys. On the gpg command line, the command key 1 will select the first subkey. Repeat for the other subkeys e.g. key 2 and key 3. This will select them all and prompt you with a warning that you are about to take action on several keys.

gpg> key 1
gpg> key 2
gpg> key 3

sec  rsa4096/5BB58AFFDF8ED9D6
     created: 2018-12-19  expires: 2021-09-09  usage: C
     trust: ultimate      validity: ultimate
ssb* rsa4096/1C434F4FBB0FE8B5
     created: 2018-12-19  expires: 2021-09-09  usage: E
ssb* rsa4096/6012253B4117B6DF
     created: 2018-12-19  expires: 2020-12-18  usage: S
ssb* rsa4096/641EAE1AB4833D26
     created: 2018-12-19  expires: 2020-12-18  usage: A
[ultimate] (1)  Nikhil Nygaard <[email protected]>
[ultimate] (2). Nikhil Nygaard <[email protected]>

gpg> expire
Are you sure you want to change the expiration time for multiple subkeys? (y/N) y
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 2y
Key expires at Thu Sep  9 08:49:07 2021 PDT
Is this correct? (y/N) y

sec  rsa4096/5BB58AFFDF8ED9D6
     created: 2018-12-19  expires: 2021-09-09  usage: C
     trust: ultimate      validity: ultimate
ssb* rsa4096/1C434F4FBB0FE8B5
     created: 2018-12-19  expires: 2021-09-09  usage: E
ssb* rsa4096/6012253B4117B6DF
     created: 2018-12-19  expires: 2021-09-09  usage: S
ssb* rsa4096/641EAE1AB4833D26
     created: 2018-12-19  expires: 2021-09-09  usage: A
[ultimate] (1)  Nikhil Nygaard <[email protected]>
[ultimate] (2). Nikhil Nygaard <[email protected]>

gpg> save

That's it. Your keys have been updated to have some more time on them. They will still expire, but that time has been pushed in to the future for the smarter version of yourself to deal with.

You can see that your public key has changed though…

diff old.pub <(gpg --armor --export 5BB58AFFDF8ED9D6)

However, its fingerprint has not. So it can still be validated as the same public key. Private keys never change, they just let you make modifications to your public key.

Now follow the instructions to export your keys again. We're going to make another revocation certificate just in case.

gpg --output 5BB58AFFDF8ED9D6.rev --gen-revoke 5BB58AFFDF8ED9D6
gpg --export-secret-subkeys --armor 5BB58AFFDF8ED9D6 > 5BB58AFFDF8ED9D6.sub.sec.asc
gpg --export-secret-keys --armor 5BB58AFFDF8ED9D6 > 5BB58AFFDF8ED9D6.sec.asc
gpg --export --armor 5BB58AFFDF8ED9D6 > 5BB58AFFDF8ED9D6.pub.asc

Now you have all your keys. Move them to your offline storage and delete your private [C] key from your computer.

gpg --delete-secret-key 5BB58AFFDF8ED9D6
gpg --delete-key 5BB58AFFDF8ED9D6

I delete the public key too just because it will be added when I import my subkeys anyways.

gpg --import 5BB58AFFDF8ED9D6.sub.sec.asc

Now that you have them all imported again, you should “ultimately” trust them. I still don't fully understand the web of trust, that is a topic for another article. You can see this article for a brief explanation.

gpg --edit-key 5BB58AFFDF8ED9D6
gpg (GnuPG) 2.2.17; Copyright (C) 2019 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 subkeys are available.

pub  rsa4096/5BB58AFFDF8ED9D6
     created: 2018-12-19  expires: 2021-09-09  usage: C
     trust: unknown       validity: unknown
ssb  rsa4096/1C434F4FBB0FE8B5
     created: 2018-12-19  expires: 2021-09-09  usage: E
ssb  rsa4096/6012253B4117B6DF
     created: 2018-12-19  expires: 2021-09-09  usage: S
ssb  rsa4096/641EAE1AB4833D26
     created: 2018-12-19  expires: 2021-09-09  usage: A
[ unknown] (1). Nikhil Nygaard <[email protected]>
[ unknown] (2)  Nikhil Nygaard <[email protected]>

gpg> trust
pub  rsa4096/5BB58AFFDF8ED9D6
     created: 2018-12-19  expires: 2021-09-09  usage: C
     trust: unknown       validity: unknown
ssb  rsa4096/1C434F4FBB0FE8B5
     created: 2018-12-19  expires: 2021-09-09  usage: E
ssb  rsa4096/6012253B4117B6DF
     created: 2018-12-19  expires: 2021-09-09  usage: S
ssb  rsa4096/641EAE1AB4833D26
     created: 2018-12-19  expires: 2021-09-09  usage: A
[ unknown] (1). Nikhil Nygaard <[email protected]>
[ unknown] (2)  Nikhil Nygaard <[email protected]>

Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)

  1 = I don't know or won't say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu

Your decision? 5

Perfect, now we're back to the way we were but with updated expiry dates.

sec#  rsa4096/5BB58AFFDF8ED9D6 2018-12-19 [C] [expires: 2021-09-09]
      Key fingerprint = 1FD5 D4A1 F326 8A90 9A5C  BFC7 5BB5 8AFF DF8E D9D6
uid                 [ultimate] Nikhil Nygaard <[email protected]>
uid                 [ultimate] Nikhil Nygaard <[email protected]>
ssb   rsa4096/1C434F4FBB0FE8B5 2018-12-19 [E] [expires: 2021-09-09]
ssb   rsa4096/6012253B4117B6DF 2018-12-19 [S] [expires: 2021-09-09]
ssb   rsa4096/641EAE1AB4833D26 2018-12-19 [A] [expires: 2021-09-09]

Your ssh control keygrip will stay the same so all your SSH Agent configurations via the GPG Agent will still work. Your git signing key will stay the same so your commits are still signed by you. I would recommend deleting your public key from GitLab and GitHub and just uploading your newly modified one though. Just for consistency.

All done! 🤗