INFRASTRUCTURE2026-04-09📖 3 min read

Amazon S3 Encryption Guide: Understanding SSE-S3, SSE-KMS, and SSE-C

Amazon S3 Encryption Guide: Understanding SSE-S3, SSE-KMS, and SSE-C

A practical comparison of Amazon S3's server-side encryption options — SSE-S3, SSE-KMS, and SSE-C — covering how default encryption works post-2023, setup instructions, cost breakdowns, and a decision flowchart to help you pick the right option for production workloads.

髙木 晃宏

代表 / エンジニア

👨‍💼

Encrypting data stored in Amazon S3 is table stakes for cloud security. But questions like "What do I actually need to configure for S3 encryption?" or "What's the difference between SSE-S3 and SSE-KMS?" come up constantly among engineers new to AWS.

This article walks through the three server-side encryption options for S3, comparing their setup, trade-offs, and when to choose each one from a practical standpoint.

What Is Amazon S3 Encryption? Default Behavior Since 2023

S3 encryption refers to the mechanism by which objects (files) stored in S3 are encrypted using the AES-256 algorithm, so that unauthorized access cannot reveal the underlying data.

On January 5, 2023, AWS made a significant change: every new object uploaded to S3 is now automatically encrypted with SSE-S3 (AES-256) by default.

In other words, your S3 data is encrypted out of the box — you don't have to do anything. That said, whether the default is enough, or whether you should opt into KMS-backed keys, depends on your project's security requirements.

Comparing the Three S3 Server-Side Encryption Methods

S3 supports three server-side encryption (SSE) methods:

AspectSSE-S3SSE-KMSSSE-C
Full nameSSE with S3 managed keysSSE with KMS managed keysSSE with customer-provided keys
Key ownerAWS (S3 service)AWS KMSThe user
Key rotationAutomatic (AWS-managed)Automatic or manual (configurable)User's responsibility
Access-control granularityS3 bucket policy onlyKMS key policy + IAMFully controlled by the user
Audit logs (CloudTrail)NoneYes (logs every key usage)None
Extra costFreeKMS API request chargesFree (but you bear key-management cost)
Default since✅ (Jan 2023)Manual configurationManual configuration
Typical use caseGeneral data protectionCompliance-driven workloadsOrganizations with their own key-management infrastructure

How SSE-S3 Works and How to Configure It

SSE-S3 lets AWS manage the encryption keys internally within S3. Since January 2023 it's applied by default on every bucket, so you typically don't need to configure anything.

Checking an Object's Encryption Status

You can verify whether an object is encrypted with SSE-S3 via the AWS CLI:

aws s3api head-object --bucket my-bucket --key my-file.txt

If the object is SSE-S3 encrypted, the response includes:

{ "ServerSideEncryption": "AES256" }

Checking the Bucket's Default Encryption

aws s3api get-bucket-encryption --bucket my-bucket
{ "ServerSideEncryptionConfiguration": { "Rules": [ { "ApplyServerSideEncryptionByDefault": { "SSEAlgorithm": "AES256" }, "BucketKeyEnabled": false } ] } }

When SSE-S3 Is Enough

For most common workloads, SSE-S3 provides adequate security. It's especially a good fit when:

  • You have no compliance requirement dictating a specific key-management scheme
  • You need your data encrypted, but you don't need audit logs of who decrypted what and when
  • You want to minimize cost

How SSE-KMS Works and How to Configure It

SSE-KMS encrypts S3 objects using keys managed by AWS Key Management Service (KMS). The biggest differences from SSE-S3 are fine-grained key access control and audit logging.

Setting SSE-KMS as the Bucket's Default Encryption

aws s3api put-bucket-encryption \ --bucket my-bucket \ --server-side-encryption-configuration '{ "Rules": [ { "ApplyServerSideEncryptionByDefault": { "SSEAlgorithm": "aws:kms", "KMSMasterKeyID": "arn:aws:kms:ap-northeast-1:123456789012:key/your-key-id" }, "BucketKeyEnabled": true } ] }'

💡 Setting BucketKeyEnabled: true turns on the S3 Bucket Key feature, which dramatically reduces the number of KMS API requests. For buckets with a high volume of objects, this single toggle can cut KMS costs substantially.

Checking the Encryption Status

For objects encrypted with SSE-KMS, the response looks like this:

{ "ServerSideEncryption": "aws:kms", "SSEKMSKeyId": "arn:aws:kms:ap-northeast-1:123456789012:key/your-key-id" }

When to Choose SSE-KMS

  • Compliance requirements: Regulated environments like PCI DSS, HIPAA, or ISMAP that require controlled key management and audit logs
  • Fine-grained access control: KMS key policies can enforce rules like "only this specific IAM role may decrypt"
  • Audit trail: CloudTrail records every key usage, so you can trace who accessed data and when
  • Cross-account access: Sharing data across AWS accounts can be controlled through KMS key policies

Watch Out for SSE-KMS Costs

SSE-KMS incurs several costs:

  • Key storage: $1 per month per customer-managed key
  • API requests: Every encrypt/decrypt call hits the KMS API, at roughly $0.03 per 10,000 requests
  • Without S3 Bucket Keys: Each PUT/GET triggers an API call, and with large data volumes the cost compounds quickly

I've personally been burned by forgetting to enable Bucket Keys before uploading a large batch of objects, and the unexpected KMS bill was memorable. If you use SSE-KMS, don't forget to set BucketKeyEnabled: true.

Where SSE-C Fits In and How to Use It

SSE-C (Server-Side Encryption with Customer-Provided Keys) requires you to send your encryption key with each request. AWS uses the key to encrypt or decrypt, then discards it — no key is stored on AWS's side.

Characteristics of SSE-C

  • You take full responsibility for generating, managing, and rotating keys
  • If you lose the key, the data becomes permanently unrecoverable (AWS can't help)
  • HTTPS is required (HTTP is not allowed)

Uploading with SSE-C

# Generate a 256-bit key KEY=$(openssl rand -base64 32) KEY_MD5=$(echo -n "$KEY" | base64 -d | openssl dgst -md5 -binary | base64) # Upload with SSE-C aws s3api put-object \ --bucket my-bucket \ --key my-file.txt \ --body my-file.txt \ --sse-customer-algorithm AES256 \ --sse-customer-key "$KEY" \ --sse-customer-key-md5 "$KEY_MD5"

Downloading with SSE-C

You must supply the same key on download:

aws s3api get-object \ --bucket my-bucket \ --key my-file.txt \ --sse-customer-algorithm AES256 \ --sse-customer-key "$KEY" \ --sse-customer-key-md5 "$KEY_MD5" \ downloaded-file.txt

When to Choose SSE-C

SSE-C is rarely the right choice for typical use cases. Consider it only for specialized scenarios like:

  • Integrating with an in-house key-management system (e.g., HSM)
  • Regulations that prohibit delegating key management to AWS
  • Multi-cloud environments where encryption keys must be centrally managed

Client-Side Encryption (CSE) as an Alternative

Everything above — SSE-S3, SSE-KMS, and SSE-C — is server-side encryption, meaning data is encrypted on S3's servers.

By contrast, Client-Side Encryption (CSE) encrypts data within the application before uploading it to S3.

Because S3 only ever sees already-encrypted data, even AWS's internal processes can't see the contents. This offers the highest security posture, but at the cost of implementing encryption and decryption logic in your application code — adding significant development and operational overhead.

Decision Flowchart for S3 Encryption

Q1: Do you have compliance requirements dictating specific key management? ├── No → SSE-S3 (stick with the default) └── Yes └── Q2: Can you delegate key management to AWS? ├── Yes → SSE-KMS └── No └── Q3: Do you have an in-house key-management system? ├── Yes → SSE-C └── No → SSE-KMS (KMS customer-managed keys are the pragmatic answer)

When in doubt, start with SSE-S3 (the default) and move to SSE-KMS once compliance requirements emerge. That's the most reliable path. Existing objects can be re-encrypted in bulk via S3 Batch Operations.

Summary

Here's a concise wrap-up of S3 encryption:

MethodKey managementCostAudit logsRecommendation
SSE-S3AWS (automatic)FreeNone★★★ (default)
SSE-KMSKMSAPI chargesYes★★☆ (for compliance)
SSE-CUserFreeNone★☆☆ (specialized needs only)

Since 2023, every object stored in S3 is encrypted by default with SSE-S3. For most projects that default is sufficient — but if you need audit logs or granular access control, it's worth moving to SSE-KMS.