Provision an encryption identity¶
By the end of this you'll have a certification primary key, an ECDH encryption subkey, and the two IAM roles that use them — all in AWS KMS, with neither private half ever leaving it. You'll finish by downloading the public key you would eventually publish.
Allow about twenty minutes. Most of that is waiting on tofu apply.
What this does not cover¶
You will not end up with a publishable OpenPGP certificate, and you will
not decrypt anything. Assembling the certificate and decrypting messages are
code, they live in sigillum, and at
the time of writing an end-to-end decrypt through DeriveSharedSecret has not
yet been demonstrated. This tutorial stops at the infrastructure, which is the
part that works today.
That is worth knowing before you start, because it changes whether this is useful to you right now.
Before you start¶
You'll need:
- OpenTofu 1.12.5 or later. Terraform will mostly work, but this module
drives
prevent_destroyfrom a variable, which OpenTofu allows and Terraform does not. - AWS credentials for an account you don't mind creating keys in. A sandbox is ideal.
- Two IAM role ARNs that already exist in that account — one to read, one to certify. They can be the same role while you're learning.
Two asymmetric KMS keys cost about $2/month while they exist, and you cannot delete them for at least 7 days once you schedule deletion. Use a sandbox.
Write the configuration¶
Make a directory and put this in main.tf. Replace the four ARNs with real
ones from your account.
terraform {
required_version = "~> 1.12.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
}
provider "aws" {
region = "eu-west-2"
}
module "identity" {
source = "gitlab.com/phpboyscout/encryption-kms/aws"
version = "~> 0.1"
name = "tutorial-identity-v1"
description = "Learning the encryption-kms module"
reader_principal_arns = ["arn:aws:iam::111122223333:role/your-role"]
certifier_principal_arns = ["arn:aws:iam::111122223333:role/your-role"]
key_administrator_arns = ["arn:aws:iam::111122223333:role/your-role"]
automation_role_arn = "arn:aws:iam::111122223333:role/your-role"
}
output "encrypt_alias" {
value = module.identity.encryption_key_alias_name
}
The -v1 on the name is deliberate. An OpenPGP identity is superseded by
minting a new one rather than editing this one, so the version belongs in the
name from the start.
Apply it¶
You'll see six resources planned: two aws_kms_key, two aws_kms_alias, and
two aws_iam_role. Apply takes a minute or so — KMS key creation is not
instant.
When it finishes:
Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
Outputs:
encrypt_alias = "alias/tutorial-identity-v1-encrypt"
Confirm the keys are what you expect¶
Check the encryption subkey first. This is the one that has to be a key-agreement key — if it came out as anything else, nothing downstream will work:
aws kms describe-key --key-id alias/tutorial-identity-v1-encrypt \
--query 'KeyMetadata.{Usage:KeyUsage,Spec:KeySpec,Algos:KeyAgreementAlgorithms}'
KEY_AGREEMENT with ECDH available is the whole point. A key that says
ENCRYPT_DECRYPT here cannot decrypt OpenPGP at all — see
why RSA cannot work.
Now the certification primary:
aws kms describe-key --key-id alias/tutorial-identity-v1-certify \
--query 'KeyMetadata.{Usage:KeyUsage,Spec:KeySpec}'
Two keys, two usages. KMS fixes key usage at creation and allows only one per key, which is why an OpenPGP identity needs both.
Download the public key¶
This is the half that eventually gets published:
aws kms get-public-key \
--key-id alias/tutorial-identity-v1-encrypt \
--output text --query PublicKey | base64 -d > subkey.der
You now have a DER-encoded SubjectPublicKeyInfo. Confirm it is the curve you
asked for:
— is what you would see for the wrong key type. You should instead see:
with ASN1 OID: prime256v1 further down. That is NIST P-256, the curve
OpenPGP calls nistp256.
Clean up¶
The module sets prevent_destroy = true on both keys, so a plain destroy is
refused — deliberately, because deleting an encryption key destroys the
ability to read everything ever encrypted to it.
To tear down a tutorial identity, set the flag to false first:
Then tofu apply to update the lifecycle rule, and tofu destroy. The keys
enter a 30-day pending-deletion window rather than disappearing; you'll keep
paying for them until it expires, and you can cancel with
aws kms cancel-key-deletion if you change your mind.
Where to go next¶
- Use it with IAM Identity Center — the most common real deployment, and the easiest to get wrong.
- The two-key structure — why an encryption key cannot stand alone.
- Inputs and outputs — everything the module takes and returns.