AWS KMS CLI
I work with AWS KMS regularly, and in this post I want to share what I’ve learned about the key management service and how to use it from the command line.
What is KMS?
KMS is AWS’s managed encryption key service. If you need to encrypt anything in AWS, you’ll end up using it.
It’s a regional service – your keys stay in the region where you create them and never leave KMS or that region. KMS handles the creation, rotation, and lifecycle of encryption keys so you don’t have to manage that infrastructure yourself.
KMS keys (originally called “Customer Master Keys” or CMKs – AWS renamed them in 2022) are the core concept. Think of a KMS key as a logical reference to the actual cryptographic material stored inside KMS. You never see or touch the raw key material directly (unless you import your own).
KMS is a good fit for encrypting small secrets like database passwords or API keys that you store in Systems Manager Parameter Store. A KMS key can encrypt and decrypt data up to 4 KB. Most AWS services that support encryption integrate with KMS under the hood.
How much does KMS cost?
You pay per API call. Every encrypt, decrypt, list-keys, or generate-data-key request has a cost. There’s also a monthly fee for each KMS key you keep. Check the AWS KMS pricing page for current rates – it’s cheap for typical workloads but can add up if you’re making thousands of calls per second.
KMS and CloudTrail
KMS logs all API requests through CloudTrail. This is useful for compliance because you can see exactly who encrypted or decrypted what, and when. The CloudTrail logs land in S3.
KMS is FIPS 140-2 Level 2 validated. FIPS is a U.S. government standard for cryptographic modules. Level 2 means the system provides evidence of tampering. CloudHSM goes further with Level 3 – check our CloudHSM comparison post if you need that level of assurance.
The KMS key types
There are three categories:
AWS-managed keys are free. AWS creates them automatically when you first use encryption in a service like S3 or EBS. You can view and audit them, but AWS controls the lifecycle and rotation schedule (every 3 years).
Customer-managed keys are the ones you create yourself. You have full control over the key policy, who can use it, when it rotates, and when it gets deleted. This is what most teams use for production workloads.
AWS-owned keys are a collection of keys that AWS services manage across multiple accounts. You can’t see them, use them, track them, or audit them. They protect resources in your account but are completely opaque to you.
Types of encryption for KMS keys
KMS supports both symmetric and asymmetric keys.
Symmetric keys
When you create a KMS key, you get a symmetric key by default. It uses AES-256 and the same key handles both encryption and decryption. Your data never leaves AWS unencrypted – you call the KMS API, and the encryption happens inside KMS.
All AWS services that integrate with KMS use symmetric keys. You’ll use symmetric keys for encrypt, decrypt, and re-encrypt operations. You can also use them to generate data keys and data key pairs.
Asymmetric keys
Asymmetric KMS keys have a mathematically related public/private key pair. You can share the public key with anyone, but the private key stays inside KMS. This is the same concept behind SSL certificates.
AWS supports RSA and elliptic curve (ECC) algorithms for asymmetric keys. ECC is newer and generally considered more secure than RSA for equivalent key sizes.
With asymmetric keys, the private key never leaves KMS – you call the API to use it. But you can download the public key and use it outside AWS. This is handy when you need to encrypt data in environments that can’t call KMS directly.
Note: Most AWS services that use KMS don’t support asymmetric keys. You’ll mainly use asymmetric keys for signing and verification, or for encrypting data outside of AWS.
KMS key policies
When you create a key programmatically or through the CLI, you can attach a key policy. If you don’t provide one, KMS creates a default policy.
Here’s what the default looks like:
{
"Version": "2012-10-17",
"Id": "key-default-1",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789010:root"
},
"Action": "kms:*",
"Resource": "*"
}
]
}
This default policy gives the AWS account root user full access to the key and allows IAM policies to grant access.
A warning about key policies: If you accidentally remove the root account statement from your key policy, nobody in the account can access the key – including administrators. You’ll have to contact AWS Support to recover access. Be careful when editing key policies.
What are AWS managed keys

In the KMS console, you’ll see AWS-managed keys with aliases that match the service name (for example, aws/s3 or aws/ebs). AWS handles these entirely – you don’t control their rotation or lifecycle.
Customer-managed keys are listed separately. Let’s create one from the command line.
AWS KMS S3 Encryption
KMS is a regional service, which matters when you work with S3. If you have an object in an S3 bucket encrypted with a key in us-east-1 and you need it in eu-west-1, you can’t just copy it. You have to decrypt it, move the plaintext to the other region, and re-encrypt with a key in that region.
AWS KMS CLI: Creating a key
Let’s create a KMS key and give it a description:
aws kms create-key --description "Bitslovers CMK Demo"
The response includes a lot of metadata. The important field is KeyId:
{
"KeyMetadata": {
"AWSAccountId": "123031469431",
"KeyId": "52f511eb-30df-404d-99fe-de718419c485",
"Arn": "arn:aws:kms:us-east-1:XXXXXXXX:key/52f511eb-30df-404d-99fe-de718419c485",
"CreationDate": "2021-10-06T05:53:22.667000-05:00",
"Enabled": true,
"Description": "Bitslovers CMK Demo",
"KeyUsage": "ENCRYPT_DECRYPT",
"KeyState": "Enabled",
"Origin": "AWS_KMS",
"KeyManager": "CUSTOMER",
"CustomerMasterKeySpec": "SYMMETRIC_DEFAULT",
"EncryptionAlgorithms": [
"SYMMETRIC_DEFAULT"
],
"MultiRegion": false
}
}
Save the KeyId somewhere – you’ll need it for the next commands.
Creating an alias
An alias is a friendly name that points to a key. The advantage is that you can point an alias at a different key without changing your application code. This makes key rotation much easier.
aws kms create-alias --target-key-id 52f511eb-30df-404d-99fe-de718419c485 --alias-name "alias/bitslovers"
To verify it was created:
aws kms list-keys
Or list aliases:
aws kms list-aliases
Key rotation

You can enable automatic key rotation in the console or via CLI. For customer-managed symmetric keys, KMS rotates the key material once per year (you can also set a custom rotation period since late 2022). AWS-managed keys rotate every three years.
Since 2023, automatic key rotation also supports asymmetric and HMAC key types. You can also trigger on-demand rotation using the RotateKeyOnDemand API.
aws kms enable-key-rotation --key-id 52f511eb-30df-404d-99fe-de718419c485
To check the rotation status:
aws kms get-key-rotation-status --key-id 52f511eb-30df-404d-99fe-de718419c485
AWS KMS CLI: Encrypt a local file
Let’s walk through encrypting and decrypting a file. First, create a test file:
echo "Bitslovers.com secret text" > /tmp/secret.txt
Now encrypt it:
aws kms encrypt \
--key-id "alias/bitslovers" \
--plaintext fileb:///tmp/secret.txt \
--output text \
--query CiphertextBlob
Note: Use fileb:// (not file://) for binary file input. On AWS CLI v2, you may also need --cli-binary-format raw-in-base64-out if you’re passing raw strings instead of base64-encoded content.
The output is a base64-encoded ciphertext blob:
AQICAHhQz9Nugb8llpXYCZrgdbOP6MRy8gS0iQ/m5WzvMrhCWgGUG/XR2HGW7KWgi9lwU+M0AAAAejB4BgkqhkiG9w0BBwagazBpAgEAMGQGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMeLTF9ZQdESTzY3xyAgEQgDeqXVJVAXxlrdanpvRgzXPOjin5mv6s2vAegcbPeLHOvU54TMfUU4gd5VzqU0mM8+wUlnpwYXyJ
I used the alias here, but you can also reference the key by its KeyId.
The output is base64-encoded. To save the actual encrypted binary to a file, pipe it through base64 --decode:
aws kms encrypt \
--key-id "alias/bitslovers" \
--plaintext fileb:///tmp/secret.txt \
--output text \
--query CiphertextBlob \
--region us-east-1 | base64 --decode > /tmp/secret.txt.encrypted
AWS KMS CLI: Decrypt a local file
The encrypted file is binary, not base64. So for decryption, use fileb:// to read it:
aws kms decrypt \
--ciphertext-blob fileb:///tmp/secret.txt.encrypted \
--output text \
--query Plaintext | base64 --decode
One thing I like about the decrypt operation: you don’t need to specify which key to use. The encrypted blob contains metadata that references the KMS key used during encryption, so KMS figures it out automatically.
The 4 KB limit and envelope encryption
KMS can only encrypt up to 4 KB per API call. If you need to encrypt larger files, you use a data encryption key (DEK) instead.
Generate one like this:
aws kms generate-data-key --key-id "alias/bitslovers" --key-spec AES_256
This returns two things: a plaintext data key and the same key encrypted by your KMS key (the ciphertext blob). The response looks something like this:
{
"CiphertextBlob": "AQIDAHUPz5...truncated...",
"Plaintext": "dGhpcyBpcyBhIHBsYWlu...(base64 encoded 32-byte key)",
"KeyId": "arn:aws:kms:us-east-1:123456789012:key/52f511eb-30df-404d-99fe-de718419c485"
}
Here’s how envelope encryption works:
- Use the plaintext data key to encrypt your data locally (no KMS API call needed).
- Save the ciphertext blob alongside your encrypted data.
- Delete the plaintext data key from memory.
- To decrypt later, send only the ciphertext blob to KMS to get the plaintext key back, then decrypt your data locally.
This approach has a real performance benefit. Only the small data key travels over the network to KMS – your actual data stays local. For large files, this avoids network latency issues. This pattern is called envelope encryption, and it’s what the AWS Encryption SDK does under the hood.
Even if someone gets the ciphertext blob, they can’t decrypt your data without calling KMS to decrypt the blob first. As long as your KMS key policy restricts who can call Decrypt, your data is safe.
HMAC keys (added 2022)
AWS added HMAC key support to KMS in 2022. HMAC keys are symmetric keys used for generating and verifying message authentication codes. You’d use them for data integrity checks, token signing, or verifying that data hasn’t been tampered with.
Create an HMAC key:
aws kms create-key \
--key-usage GENERATE_VERIFY_MAC \
--key-spec HMAC_256
Generate a MAC:
aws kms generate-mac \
--key-id alias/hmac-key \
--message "Hello World" \
--mac-algorithm HMAC_SHA_256
Verify a MAC:
aws kms verify-mac \
--key-id alias/hmac-key \
--message "Hello World" \
--mac-algorithm HMAC_SHA_256 \
--mac "base64-encoded-mac-value"
Available HMAC key specs are HMAC_224, HMAC_256, HMAC_384, and HMAC_512.
Conclusion
KMS handles encryption key management so you don’t have to. The CLI makes it straightforward to create keys, encrypt small secrets, generate data keys for larger files, and manage rotation. For most production workloads, I recommend using customer-managed keys with rotation enabled, and envelope encryption for anything over 4 KB.
Check out the official AWS KMS documentation for the full API reference.
Other Posts Related to AWS
Understand the difference between KMS and CloudHSM: KMS vs CloudHSM.
Comments