← Blog
A cream ceramic storage box with a raised lid, dark green lining, and coral locking pin on a lavender background.
Published on
2026-11-02

S3 encryption: defaults, KMS keys, and object checks

Amazon S3 encrypts new object uploads at rest by default. The practical decision is who controls the keys, which permissions your application needs, and how you verify the encryption used by an individual object.

This guide compares SSE-S3, SSE-KMS, and DSSE-KMS, then walks through an SSE-KMS test for an S3 general purpose bucket. It also covers SSE-C and client-side encryption. Directory buckets have different restrictions and are outside this example. The commands were checked locally against AWS SDK input models; they were not run against an AWS account.

What S3 encryption protects

With server-side encryption, S3 encrypts object data for storage and decrypts it for an authorized download. Encryption at rest does not replace access controls or HTTPS for transport. A reader with the necessary permissions can still retrieve the original content.

A bucket’s default encryption setting and an object’s encryption metadata answer different questions. The first describes what S3 applies to a new upload that does not specify an encryption choice. The second records what a particular object uses. Changing the default does not rewrite existing objects.

SSE-S3, SSE-KMS, and DSSE-KMS compared

OptionKey managementPractical reason to choose itOperational consideration
SSE-S3Amazon S3 manages the keys.Automatic encryption at rest without managing KMS permissions.It does not give you a customer-managed KMS key policy.
SSE-KMSAWS KMS, with an AWS managed or customer managed key.Use a customer managed key when you need control over its access policy and lifecycle.Account for KMS permissions, request charges, and quotas.
DSSE-KMSKMS and S3 apply two independent encryption layers.Meet a documented requirement for two layers of server-side encryption.Additional charges apply; S3 Bucket Keys are not supported.

SSE-S3 is the baseline for new uploads. SSE-KMS adds key-management choices, while DSSE-KMS adds a second layer. Choose from the access and key-management requirements of the workload; encryption mode alone does not establish compliance.

SSE-C and client-side encryption are different

With SSE-C, you supply an encryption key with relevant requests, and S3 performs the encryption. AWS changed the default in April 2026: SSE-C is blocked for new general purpose buckets and for existing buckets in accounts with no SSE-C encrypted objects. Workloads that need it must enable it explicitly. It is not a bucket default encryption mode.

With client-side encryption, your application encrypts the payload before uploading it. S3 receives ciphertext. You must plan how authorized clients obtain keys and recover data; selecting SSE-KMS by itself does not provide this model.

Prepare a small SSE-KMS test

Use a dedicated, empty general purpose test bucket and a symmetric customer managed KMS key in the same AWS Region. This example uses eu-west-1. Replace the demonstration bucket name, account ID, Region, and key ARN everywhere before running anything. Use a current AWS CLI that supports the encryption configuration fields shown below.

Confirm your caller, inspect the key, and record the existing bucket configuration:

aws sts get-caller-identity
aws kms describe-key --key-id arn:aws:kms:eu-west-1:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab --region eu-west-1
aws s3api get-bucket-encryption --bucket amzn-s3-demo-encryption --expected-bucket-owner 123456789012 --region eu-west-1

Confirm the key is enabled and intended for symmetric encryption. The test principal needs the relevant S3 configuration, write, and read permissions, plus permission to describe and use the selected KMS key. Check both IAM and the KMS key policy. For this upload/download exercise, allow the required kms:GenerateDataKey and kms:Decrypt operations on that key.

Do not use a server-access-log destination for this exercise: AWS requires SSE-S3 for that destination. Do not apply this example to a shared application bucket without reviewing its existing encryption rules, writers, and policies.

Set and read back the bucket default

Save the following as encryption.json. It selects SSE-KMS, enables an S3 Bucket Key, and explicitly blocks new SSE-C writes. The ARN is a placeholder for your test key.

{
  "Rules": [
    {
      "ApplyServerSideEncryptionByDefault": {
        "SSEAlgorithm": "aws:kms",
        "KMSMasterKeyID": "arn:aws:kms:eu-west-1:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab"
      },
      "BucketKeyEnabled": true,
      "BlockedEncryptionTypes": {
        "EncryptionType": [
          "SSE-C"
        ]
      }
    }
  ]
}

The put-bucket-encryption command writes the configuration supplied in the file. After applying it, read it back:

aws s3api put-bucket-encryption --bucket amzn-s3-demo-encryption --server-side-encryption-configuration file://encryption.json --expected-bucket-owner 123456789012 --region eu-west-1
aws s3api get-bucket-encryption --bucket amzn-s3-demo-encryption --expected-bucket-owner 123456789012 --region eu-west-1

Compare the returned algorithm, full key ARN, Bucket Key flag, and blocked encryption types with your file. The API documentation warns that S3 does not validate the KMS key ID when setting a general purpose bucket’s default. A successful configuration response therefore does not prove an upload or download will work.

Understand the Bucket Key setting

S3 Bucket Keys reduce the number of requests S3 makes to KMS for SSE-KMS. Savings depend on request patterns and requesters; they are not a fixed discount on your storage bill. Bucket Keys also use the bucket ARN, rather than the object ARN, as the KMS encryption context. Review policies that rely on an object-specific context before enabling them. DSSE-KMS cannot use this option.

Upload a sample and verify the actual object

Create a small local text file named encryption-check.txt with harmless sample content. This put-object request omits encryption headers so it exercises the bucket default:

aws s3api put-object --bucket amzn-s3-demo-encryption --key encryption-check/sample.txt --body encryption-check.txt --if-none-match "*" --expected-bucket-owner 123456789012 --region eu-west-1

The quoted --if-none-match "*" prevents an ordinary overwrite if that key already exists. A 412 response means the precondition failed; choose a fresh test key and use it consistently in the remaining commands. An upload can also fail if a bucket policy requires explicit encryption headers. In that case, test your intended writer behavior separately rather than removing the policy.

Inspect the object’s encryption metadata:

aws s3api head-object --bucket amzn-s3-demo-encryption --key encryption-check/sample.txt --expected-bucket-owner 123456789012 --region eu-west-1 --query "{Algorithm:ServerSideEncryption,Key:SSEKMSKeyId,BucketKey:BucketKeyEnabled}"

For this example, expect aws:kms, your full KMS key ARN, and BucketKey: true. These are expected values, not output from a deployment we performed. The HeadObject reference explains the response fields. Do not send upload encryption headers on an SSE-KMS HEAD request.

Finally, retrieve the object with the intended reader identity, using a separate CLI profile if the application reads and writes through different roles:

aws s3api get-object --bucket amzn-s3-demo-encryption --key encryption-check/sample.txt --expected-bucket-owner 123456789012 --region eu-west-1 downloaded-encryption-check.txt

Compare the downloaded content with the original. A successful metadata check is not a substitute for a successful read using the real reader’s permissions. Keep the test key, caller identity, expected encryption, and outcome together so that another engineer can repeat the check.

A default is not an enforcement policy

For general purpose buckets, an upload that explicitly requests another permitted encryption choice can override the default. If every writer must use one KMS key, review the default-encryption behavior and the bucket policy together.

A policy that requires encryption headers can reject requests that would otherwise inherit the correct default. Test the actual clients, service integrations, and multipart upload path. Our S3 bucket policy guide explains how to scope actions, resources, and conditions. Avoid pasting a new complete policy over existing statements.

Plan existing-object changes separately

AWS now supports UpdateObjectEncryption for eligible existing objects: SSE-S3 to SSE-KMS, changing a KMS key, or enabling Bucket Keys. It avoids copying the payload. Source objects using SSE-C or DSSE-KMS, unencrypted objects, and objects under Object Lock retention or legal hold are excluded. Review the operation’s version, account, and replication restrictions before planning a migration; never remove retention controls simply to run this example.

Track which object versions you intend to change. Our S3 versioning guide explains why the current version and older versions need separate attention. Verify a small representative set before scheduling a bulk operation, and retain a completion report.

Encrypted replication also needs its own permissions and configuration. Read AWS’s encrypted-object replication guidance alongside our S3 replication guide. Check the replica’s encryption and reader access; changing a source object’s encryption does not establish that the destination has been updated.

Diagnose failures before broadening access

  • Configuration succeeds, upload fails: check the full key ARN, Region, key state, writer permissions, and explicit denies.
  • Upload succeeds, download fails: check the reader’s S3 access and KMS decrypt permissions, including cross-account key-policy requirements.
  • An old object uses the previous key: inspect that object or version; a new bucket default does not migrate it.
  • SSE-C uploads return 403: inspect the blocked-encryption setting before assuming the object policy is wrong.
  • KMS costs are higher than expected: review request volume, Bucket Key eligibility, and the workload’s actual pattern before estimating savings.

Keep the key available for as long as stored objects, versions, or recovery copies depend on it. AWS’s key-deletion guidance explains why removing a needed key can make data unrecoverable. A useful encryption check covers both the stored configuration and an authorized read, with key ownership and recovery responsibilities recorded.

Your next workload belongs on Hivenet.

Pick one AI, compute, or storage workload and see the difference for yourself. Spin it up in minutes, or let our team map your fastest path to production.