Skip to main content

AWS KMS โ€” Key Management Service

Core concept: KMS manages encryption keys. AWS services use KMS internally (S3 SSE-KMS, RDS, EBS). You can also use KMS directly in your apps.


Key Typesโ€‹

TypeDescriptionRotationUse
AWS Managed KeyAuto-created when you enable encryption in a serviceEvery 1 year (automatic)Service-default encryption
Customer Managed Key (CMK)You create and controlYou configure (annual or manual)Full control, cross-account, custom policies
AWS-Owned KeyShared across customers, not visibleAWS managedFree, no audit trail

CMK Key Materialโ€‹

SourceDescription
KMS (default)AWS generates and stores key material
External (BYOK)You import your own key material
CloudHSMKey material stored in a hardware security module

Envelope Encryptionโ€‹

KMS directly encrypts data up to 4KB. For larger data, use envelope encryption:

Your Plaintext Data (large)
โ”‚
โ–ผ
Generate Data Key (DEK)
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Plaintext DEK โ†’ encrypt data โ”‚
โ”‚ Encrypted DEK โ†’ stored with data โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚
โ–ผ
Store: Encrypted Data + Encrypted DEK

To Decrypt:
KMS decrypts the Encrypted DEK โ†’ Plaintext DEK โ†’ decrypts data
KmsClient kms = KmsClient.create();

// Generate a data key
GenerateDataKeyResponse keyResponse = kms.generateDataKey(
GenerateDataKeyRequest.builder()
.keyId("arn:aws:kms:us-east-1:123456789012:key/my-key-id")
.keySpec(DataKeySpec.AES_256)
.build());

byte[] plaintextKey = keyResponse.plaintext().asByteArray(); // Encrypt data locally
byte[] encryptedKey = keyResponse.ciphertextBlob().asByteArray(); // Store alongside ciphertext

// Decrypt data key later
DecryptResponse decryptResponse = kms.decrypt(
DecryptRequest.builder()
.ciphertextBlob(SdkBytes.fromByteArray(encryptedKey))
.build());

KMS API Operationsโ€‹

APIDescription
EncryptEncrypt up to 4KB directly
DecryptDecrypt ciphertext
GenerateDataKeyGet plaintext + encrypted DEK
GenerateDataKeyWithoutPlaintextGet only encrypted DEK (encrypt later)
ReEncryptRe-encrypt under a different key (plaintext never leaves KMS)
DescribeKeyGet key metadata

Key Policiesโ€‹

Every CMK has a resource-based policy. Without a key policy that grants access, IAM policies alone won't work:

{
"Sid": "Allow Lambda role to use this key",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::123456789012:role/LambdaRole" },
"Action": ["kms:Decrypt", "kms:GenerateDataKey"],
"Resource": "*"
}

KMS Limits (API Throttling!)โ€‹

APIDefault TPS
Encrypt / Decrypt5,500 โ€“ 30,000/s (region-dependent)
GenerateDataKeySame
Throttling at scale

If your Lambda is called 10,000 times/second and each call does kms:Decrypt, you'll hit KMS throttling.

Fix: Use Data Key Caching (with AWS Encryption SDK) โ€” cache the plaintext DEK in memory, reducing KMS calls.


๐Ÿงช Practice Questionsโ€‹

Q1. A Lambda function needs to encrypt a 50MB file before storing it in S3. Which approach should the developer use?

A) Call kms:Encrypt with the 50MB file
B) Use Envelope Encryption โ€” generate a data key and encrypt locally
C) Use S3 SSE-S3
D) Call kms:GenerateDataKey 50 times

โœ… Answer & Explanation

B โ€” KMS can only encrypt data up to 4KB directly. For larger data, use envelope encryption: GenerateDataKey โ†’ encrypt data locally with the plaintext DEK โ†’ store encrypted DEK alongside ciphertext โ†’ delete plaintext DEK from memory.


Q2. A developer wants to re-encrypt S3 objects that were encrypted with Key A, using Key B instead, without ever exposing the plaintext. Which KMS API should they use?

A) Decrypt โ†’ Encrypt
B) ReEncrypt
C) GenerateDataKey
D) RotateKey

โœ… Answer & Explanation

B โ€” ReEncrypt performs a server-side re-encryption entirely within KMS. The plaintext never leaves KMS and never appears in your code.


๐Ÿ”— Resourcesโ€‹