Client-Side Encryption: The Only Way to Encrypt S3 Data Before It Leaves Your Machine

Ned
Ned Cloud Engineer
· Updated · 3 min read
Client-Side Encryption: The Only Way to Encrypt S3 Data Before It Leaves Your Machine

The Problem

A centralized account collects log data into multiple S3 buckets. Requirements:

  • Data must be encrypted before upload (not just after arrival at S3)
  • Data must be encrypted in transit

Server-side encryption alone does not satisfy the “before upload” requirement.

The Solution

Use client-side encryption. The data is encrypted on your machine, then the ciphertext travels over HTTPS to S3. S3 never sees the plaintext.

How It Works

The Difference Between Client-Side and Server-Side

1
2
3
4
5
Client-Side:
[Plaintext] → encrypt locally → [Ciphertext] → HTTPS → S3 stores ciphertext

Server-Side (SSE-KMS, SSE-S3, SSE-C):
[Plaintext] → HTTPS → S3 receives plaintext → encrypt at rest

Server-side encryption means AWS sees your plaintext briefly. For strict “before upload” requirements, that is not acceptable.

Client-Side With AWS Encryption SDK + KMS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import boto3
from aws_encryption_sdk import EncryptionSDKClient, StrictAwsKmsMasterKeyProvider

client = EncryptionSDKClient()
kms_kwargs = dict(key_ids=[
    "arn:aws:kms:us-east-1:123456789012:key/abc-123"
])
master_key_provider = StrictAwsKmsMasterKeyProvider(**kms_kwargs)

with open("log.dat", "rb") as f:
    plaintext = f.read()

ciphertext, encryptor_header = client.encrypt(
    source=plaintext,
    key_provider=master_key_provider
)

# Upload the ciphertext (never plaintext) to S3
s3 = boto3.client("s3")
s3.put_object(Bucket="logs", Key="log.dat.enc", Body=ciphertext)

The AWS Encryption SDK:

  1. Calls KMS to generate a data key
  2. Encrypts the data locally with that key
  3. Wraps the encrypted data key in the ciphertext
  4. Returns ciphertext ready for upload

KMS never sees the plaintext. S3 never sees the plaintext. The plaintext existed only briefly in your process memory.

Client-Side Encryption Options

Method Key Storage Complexity
AWS Encryption SDK + KMS KMS manages the master key Low
S3 Encryption Client (deprecated) You manage the master key Medium
Custom AES-256 You manage everything High

For anything AWS-hosted, use the AWS Encryption SDK with KMS. It handles envelope encryption, key rotation, and multi-region key policies.

Why Not the Alternatives?

Server-side encryption (SSE-KMS, SSE-S3, SSE-C) — All of these encrypt after S3 receives the data. They fail the “before upload” requirement.

Bucket policy requiring SSE-S3 — This enforces server-side encryption. Same problem — encryption happens after arrival at S3.

Default KMS bucket encryption — Same server-side encryption category. Does not encrypt before upload.

Key Takeaways

  • Client-side encryption is the only way to ensure data is encrypted before it reaches AWS
  • AWS Encryption SDK + KMS is the recommended library — do not roll your own
  • KMS generates a data key, but only the encrypted form travels to S3
  • All server-side encryption options (SSE-*) encrypt after S3 receives the plaintext
  • Client-side encryption also protects against a compromised transport layer — the ciphertext is safe even if TLS fails
Rating:
Share
Previous S3 Gateway Endpoint for High-Volume Container Workloads: Free vs $1000/Month NAT Fees Next S3 Block Public Access + SCP: Two Layers That Make Accidental Public Buckets Impossible