Page MenuHome GnuPG

Kleopatra: "Change Validity" does ignore the option "Also update the validity period of the subkeys"
Closed, ResolvedPublic

Description

Details

Version
Gpg4win-4.1.1-beta284

Event Timeline

ebo created this task.

Note to self: This might happen because the key is/was expired.

This is basically working as intended by gpg --quick-set-expire. With a first call of gpg --quick-set-expire the validity of the primary key is extended. With a second call of gpg --quick-set-expire with third option * gpg is asked to update the expiration time "of all non-revoked and not yet expired subkeys".

The problem gpg (and hence Kleopatra) are faced with is that in case of multiple expired subkeys its impossible to know which subkeys to unexpire. If there is only one subkey, things may seem easier to decide, but special-casing this situtation leads down the rabbit hole.

Options:

  1. Reword "Also update the validity period of the subkeys" to "Also update the validity period of the valid subkeys" (without the highlighting of "valid") and leave everything else as-is.
  2. Disable and uncheck (or, better, hide?) the option "Also update the validity period of the subkeys" if there are no valid subkeys that this option would apply to.
  3. Change the option to "Also update the validity period of the following subkeys:" with separate check boxes for all non-revoked subkeys where still valid subkeys are checked by default and already expired subkeys are not checked by default. This option assumes that gpg --quick-set-expire allows changing the expiration time of explicitly listed subkeys even if they are already expired.

Please discuss which of the options you want.

Option #1 is good from a descriptional POV, but in most cases both the main key and the subkeys will be expired, so it would end up not updating any subkey.

Option #2 is bad since it hides the ability to update the subkeys.

Option #3 would probably work, although I wonder if it's a good UI.

I think the User history would be:

  • User creates an OpenPGP key (due to some defaults, the key uses subkeys)
  • Key expires and the user is no longer able to use the key
  • User clicks the big option to extend the lifetime of their key

Expected result:

  • The user is able to use their key again (after publishing their updated public part) just as before it expired.

The big trap here is the case where the user renews the main key but not the subkey(s), ending up with a key partially unusable (typically, one to which it's not possible to encrypt, as that was done on the subkey).

Given that in 99% of the cases the scenario will be a main key with a single subkey that also needs renewing (or maybe a couple of subkeys for different purposes, not sure if anything defaults to creating that), I find it would be a good enough solution if it simply handled that trivial case and produced an error message otherwise stating that since there are multiple subkeys Kleopatra doesn't know which to update.

@Angel thanks for the valuable feedback

Looking a bit more into this, I noticed an interesting difference between OpenPGP certificates generated by Kleopatra (with default settings) and OpenPGP certificates generated with gpg --quick-gen-key. The former generates a certificate where the primary key and the (encryption) subkey both have an explicit expiration date set. On the other hand, the latter generates a certificate where the primary key has an expiration date set, but the (encryption) subkey does not have an expiration date set (which means it implicitly expires together with the primary key).

This has interesting consequences when extending the expiration of an expired key with Kleopatra:

  • For a key generated by Kleopatra the subkey stays expired.
  • For a key generated with gpg --quick-gen-key the subkey becomes valid again with an interesting twist:
    • If the user checked the "Also update the validity period of the subkeys" option, then the subkey will get an explicit expiration date. (Note: It didn't have an explicit expiration date before this operation.)
    • On the other hand, if the user unchecks the "Also update the validity period of the subkeys" option, then the subkey will keep its unset expiration, i.e. it inherits the primary key's expiration.

Technical background:
Kleopatra uses gpgme_op_genkey (using gpg --gen-key with a keyparms "file") for generating OpenPGP certificates. As documented, gpg --gen-key uses the Expire-Date value in the keyparms as "expiration date for the key (and the subkey)".

gpg --quick-gen-key user-id [algo [usage [expire]]] uses the value of the expire command line argument only for the primary key while the subkey is created without expiration.

Incidentally, there is gpgme_op_createkey which supersedes gpgme_op_genkey (and which uses gpg --quick-gen-key).

This opens a whole new set of options to go forward:

  • Kleopatra should use the modern gpgme_op_createkey instead of the old gpgme_op_genkey. This would make this issue a non-issue for newly created keys because the subkey of a default generated certificate would no longer have an explicit expiration date and thus it always expires together with the primary key.
  • Kleopatra should not set an explicit expiration date on a subkey that currently doesn't have an explicit expiration date when the user changes the validity period of an OpenPGP certificate. This ensure that the subkey keeps its property to expire together with the primary key.
  • Kleopatra should gracefully handle older keys where the (only) subkey has the same explicit expiration date as the primary key, i.e. it should set the expiration date of this subkey to the same value as the expiration date of the primary key.
  • For any expired subkeys with different expiration date than the primary key the current behavior is kept (maybe with an additional notification about unchanged subkeys).

Adding @werner @aheinecke to get their feedback especially on the options at the end of the previous comment.

I had two arguments about using gpg_op_createkey, first it was only available on "recent" gnupg versions. That is obsolete now.
Secondly it required you to add each subkey one after another. With rentering the passphasre. This could lead to error behaviors are was just confusing. But otherwise I am all for it. But I think changing this now is a bit too invasive.

I think the most important one is part 3. As this will be the main case our customers are affected with.
The second part also makes sense to me.

And yes there are use cases where people roll over their encryption subkeys regularly so we should of course also cater to them.

There are pros and cons for both key generation versions. I can't remember whether or why I decided that --quick-gen-key should behave different. Maybe because the creation of the subkey was added a bit later or because a new internal API is used here.

When changing the expiration date it is useful to also create a new encryption subkey; in this case having an explicit expiration date on the old subkey seems to be best choice so that the old subkey can't be used accidentally.

Option 3 sounds best to me. If the newest encryption subkey has an expiration date in the same range as the primary key that subkey should also get a new expiration date.

ikloecker moved this task from Restricted Project Column to Restricted Project Column on the Restricted Project board.
ikloecker changed the task status from Open to Testing.May 4 2023, 11:35 AM
ikloecker removed ikloecker as the assignee of this task.
ikloecker moved this task from Restricted Project Column to Restricted Project Column on the Restricted Project board.

Instead of using gpg --quick-set-expire with the * wildcard for the subkeys to update, the subkeys to update are now listed explicitly. This way the last three options from my comment could be implemented, i.e.

  • Subkeys without explicit expiration are not updated. Note: This doesn't work for already expired subkeys because gpgme has no way to know whether an expired subkey has an explicit expiration set because gpg --list-colon always prints an expiration date for subkeys of expired keys.
  • Not yet expired subkeys with explicit expiration are updated.
  • Expired subkeys which expired at the same time (+/- 10 seconds) as the primary key are updated.
  • All other expired subkeys are not updated.

The first testcase (with plain testkey Xena) works, both are extended with "change validity". But the expiry day of the subkey is one day later than the date I gave.


Is this intended?

And when I set the validity to never expire (works) and afterwards set it to a date again, the date is now only set for the main key

Update: This is as designed, see https://dev.gnupg.org/T6473#170299 point one.

In T6473#170380, @ebo wrote:

And when I set the validity to never expire (works) and afterwards set it to a date again, the date is now only set for the main key

Update: This is as designed, see https://dev.gnupg.org/T6473#170299 point one.

This bothers me a bit, as I find it confusing. Werner suggested for subkeys without explicit expiry date we could show in Kleopatra the expiry date of the main key in grey to make it visually obvious that a subkey will expire implicitly when the main key expires.

What do you think?

In T6473#170571, @ebo wrote:
In T6473#170380, @ebo wrote:

And when I set the validity to never expire (works) and afterwards set it to a date again, the date is now only set for the main key

Update: This is as designed, see https://dev.gnupg.org/T6473#170299 point one.

This bothers me a bit, as I find it confusing. Werner suggested for subkeys without explicit expiry date we could show in Kleopatra the expiry date of the main key in grey to make it visually obvious that a subkey will expire implicitly when the main key expires.

What do you think?

I think it makes sense. Grey could be an accessibility problem (low contrast), so that I'd just show it with the normal text color. After all, effectively the subkey is valid until the expiration date of the primary key. That the subkey doesn't have an explicit expiration is a technical detail. Anyway, please open a new ticket for this.

It does not work as described for subkeys with later expiry dates if the primary key has already expired:


Change validity on the 12th for that key results in:

Since 2019 gpg returns the expiry date of the primary key for all subkeys if the primary key is expired, see https://dev.gnupg.org/T3343.
So as far as Kleopatra knows, all subkeys expire at the same time as the primary key. And have all an explicit expiry date, too, if I understand it correctly.

Therefore all subkeys of an expired primary are updated with an explicit expiry date.

But the usual case of extending the validity for a default GnuPG VS-D key which has already expired works.

ebo claimed this task.
ebo moved this task from Restricted Project Column to Restricted Project Column on the Restricted Project board.