The two-key structure¶
The module creates two KMS keys where you might expect one. That is structural, not a preference.
An encryption key cannot stand alone¶
An OpenPGP certificate — the thing you publish, that people encrypt to — is not a bare public key. It is a primary key, one or more User IDs, and usually one or more subkeys, held together by signatures:
flowchart TD
P["Primary key<br/>SIGN_VERIFY"]
U["User ID<br/>you@example.com"]
S["Encryption subkey<br/>KEY_AGREEMENT / ECDH"]
P -->|self-certification| U
P -->|subkey binding signature| S
Both arrows are signatures made by the primary key's private half. The self-certification asserts that this identity belongs to this key; the binding signature asserts that this subkey belongs to this certificate.
An encryption key cannot make either signature. So a certificate consisting only of an encryption key cannot be constructed — there would be nothing to bind it to, and nothing asserting who it belongs to.
Why that forces two KMS keys¶
A KMS key has exactly one KeyUsage, fixed at creation, chosen from
SIGN_VERIFY, ENCRYPT_DECRYPT, GENERATE_VERIFY_MAC and KEY_AGREEMENT. It
cannot be changed afterwards, and no value means "both".
So the signing half and the agreement half must be separate keys:
| Key | Usage | Job |
|---|---|---|
certify |
SIGN_VERIFY |
Self-certification, subkey binding, revocations |
encrypt |
KEY_AGREEMENT |
The actual decryption, via DeriveSharedSecret |
Two keys is the minimum that yields a publishable certificate. This is the detail most likely to surprise someone approaching the problem as "the signing module, but with a different key usage".
Why the primary is its own key¶
A tempting shortcut is to reuse an existing release-signing primary and just bind a new encryption subkey to it. Don't.
Coupling a contact identity to a release-signing key means a routine release-key rotation silently breaks encrypted contact — the certificate people hold is bound to a primary that no longer exists. The two things have entirely different lifecycles and entirely different reasons to rotate.
The module is therefore self-contained: its own primary, its own subkey, its own lifecycle.
What this means for the certifier role¶
Because certificate assembly is a signing operation, it needs kms:Sign on the
primary — and it needs to read the encryption key's public half to emit the
subkey packet. Both are granted to the certifier role, which is why that role
can read public keys on both keys while holding the sensitive action on only
one.
That is also why the certifier is the higher-privileged of the two roles: a binding signature is what attaches an encryption key to an identity, so whoever can make one can attach a different key. See roles and trust.
See also¶
- Why RSA cannot work — what constrains the subkey.
- Rotation, retention and deletion — why the fingerprint is the identity.