Skip to content

Retire an identity

The problem

You need to stop people encrypting to the current certificate — because it is old, or because you suspect the key is compromised — while keeping every message that was already sent readable.

The rule that governs this

[!CAUTION] Never delete the retired key. Anything encrypted against the old certificate is still bound to the old key. Delete it and that mail becomes permanently unreadable, including anything sitting unread in a queue.

Retire by superseding and disabling, never by destroying. See rotation, retention and deletion for why deletion — not rotation — is the operation that loses messages.

Steps

1. Stand up the replacement alongside the old one

Add a second module block. Do not edit the existing one — changing encryption_key_spec or certify_key_spec is ForceNew and would destroy the key you are trying to preserve.

module "identity_v1" {
  # ... unchanged, stays exactly as it is
}

module "identity_v2" {
  source  = "gitlab.com/phpboyscout/encryption-kms/aws"
  version = "~> 0.1"

  name = "confidential-intake-v2"   # note the version bump
  # ... same principals as v1
}

The -vN suffix is why the module tells you to put a version in the name. For an OpenPGP identity the fingerprint is the identity, so a new one is a new key, not an edit.

2. Publish the new certificate

Assemble and publish the v2 certificate, and update the Encryption: field (or equivalent pointer) to reference it. Senders will pick up the new certificate on their next fetch.

3. Leave v1 in place and keep reading it

Do nothing to the v1 keys. The reader role for v1 stays, and archived mail stays readable. You are now running two identities, which is correct and expected during the overlap.

4. Optionally disable the v1 encryption key — much later

Once you are confident nothing new is arriving on v1 and the archive has been processed, you may disable it:

aws kms disable-key --key-id "$(tofu output -raw v1_encryption_key_id)"

A disabled key cannot decrypt, so this is reversible but not free — re-enable it before touching the archive again. If in any doubt, leave it enabled. An enabled key costs about $1/month; an unreadable archive costs more.

5. Do not schedule deletion

There is almost never a reason to. If you are decommissioning the whole system and are certain nothing will ever need reading again, the module requires two deliberate steps:

allow_administrator_key_deletion = true   # then apply
prevent_destroy                  = false  # then apply

Both defaults exist to make that sequence hard to perform by accident. The 30-day deletion window then gives one final chance to cancel with aws kms cancel-key-deletion.

If the key is actually compromised

Superseding does not un-send anything. An attacker holding the private half of a compromised encryption key can read everything ever sent to it, and rotating does not change that. Rotation limits future exposure only.

Treat it as an incident: rotate, publish, and assume the archive is known to the attacker.

See also