Open-Source Wikis

/

MinIO

/

Systems

/

KMS and encryption

minio/minio

KMS and encryption

Server-side encryption (SSE-S3, SSE-KMS, SSE-C) is implemented in two layers: a low-level crypto package (internal/crypto/) and a key-management abstraction (internal/kms/). The runtime exposes admin and key-rotation endpoints under /minio/kms/v1.

Purpose

  • Encrypt object data at rest with per-object data keys (DEKs) wrapped by a key encryption key (KEK).
  • Plug into an external KMS (KES, AWS KMS via KES) for KEK management.
  • Fall back to a local secret-derived KEK for development.

Layout

cmd/
├── encryption-v1.go          # SSE wiring: read/write paths
├── encryption-v1_test.go
├── kms-handlers.go           # /minio/kms/v1/*
├── kms-router.go
internal/crypto/
├── crypto.go                 # Top-level encrypt/decrypt
├── auto-encryption.go        # Server-default encryption
├── header.go                 # SSE headers
├── key.go                    # Object encryption keys
├── metadata.go               # Per-object SSE metadata
├── sse.go, sse-s3.go, sse-kms.go, sse-c.go
internal/kms/
├── config.go, single-key.go  # Local single-KEK fallback
├── kms.go                    # Public KMS interface
├── kes.go, kes-conn.go       # KES client (mTLS)
├── builtin.go                # Built-in cipher
├── policy.go                 # Encryption policy decisions
└── stub.go                   # No-op KMS

Key abstractions

Symbol File What it is
kms.KMS internal/kms/kms.go The interface every KMS backend implements.
singleKeyKMS internal/kms/single-key.go Local single-KEK; for dev/test.
kesKMS internal/kms/kes.go Production KES client.
crypto.SSE, SSEC, SSES3, SSEKMS internal/crypto/sse*.go Encrypt/decrypt wrappers per scheme.
objectEncryptionKey internal/crypto/key.go The DEK derived for each object.
EncryptedObject internal/crypto/crypto.go Helper used by the read/write paths.

How it works

graph TD
    PUT[PutObject] --> SEL{SSE header?}
    SEL -- SSE-C --> SSEC[Use client-supplied KEK]
    SEL -- SSE-KMS --> KMS[KMS.GenerateDEK]
    SEL -- SSE-S3 --> KMS
    KMS --> WRAP[Wrap DEK with KEK]
    WRAP --> ENC[Encrypt parts with DEK using sio]
    ENC --> META[Store encrypted DEK + metadata in xl.meta]

SSE schemes

  • SSE-S3. Server-managed encryption. The KMS issues a DEK; the wrapped DEK is stored alongside the object. Default-on if MINIO_KMS_AUTO_ENCRYPTION=on (internal/crypto/auto-encryption.go).
  • SSE-KMS. Same mechanism, but the client picks the KEK by name and may pass an encryption context.
  • SSE-C. The client provides the KEK with each request. MinIO never persists the KEK; only the DEK encrypted with the client KEK is stored.

The DEK encrypts payloads using github.com/minio/sio (constant-time AEAD over fixed-size segments). Per-part keys are derived in internal/crypto/key.go.

KES integration

internal/kms/kes.go opens an mTLS connection to a KES server and uses it for GenerateKey, DecryptKey, and Status calls. KES in turn can be backed by Vault, AWS KMS, GCP KMS, Azure Key Vault, or its own file-based store. The connection uses aead.dev/mtls for client-cert auth.

Local fallback

For development, singleKeyKMS derives a KEK from MINIO_KMS_SECRET_KEY (or MINIO_KMS_MASTER_KEY legacy) and provides the same interface. This is what the make test flow uses.

Auto-encryption

internal/crypto/auto-encryption.go lets an operator force every PUT through SSE-S3 even if the client didn't ask for it. The decision is made in cmd/encryption-v1.go before the data hits the erasure encoder.

Bucket encryption configuration

The S3 bucket-encryption API (cmd/bucket-encryption-handlers.go and internal/bucket/encryption/) lets each bucket pin a default encryption scheme. The header presence on a PUT overrides the bucket setting.

KMS admin endpoints

Routes in cmd/kms-router.go:

  • GET /minio/kms/v1/status
  • GET /minio/kms/v1/key/list
  • POST /minio/kms/v1/key/create
  • POST /minio/kms/v1/key/import (KES variants)

mc admin kms key is the user-facing CLI.

Key rotation

  • Per-object batch rotation. cmd/batch-rotate.go defines a batch job that re-wraps DEKs with a new KEK without re-uploading payload bytes.
  • Bucket key rotation. Triggered from mc admin kms key rotate.

Integration points

  • cmd/object-handlers.go (PUT/GET path) pulls in crypto.EncryptedObject and the KMS.
  • cmd/object-multipart-handlers.go derives per-part keys.
  • cmd/encryption-v1.go is the bridge between the handler layer and internal/crypto/.
  • internal/bucket/encryption/ parses the S3 bucket-encryption XML.

Entry points for modification

  • Add a KMS provider. Implement the kms.KMS interface in a new file under internal/kms/, register it with internal/config/, document the env vars.
  • Add an SSE variant. Place the wrapper in internal/crypto/, update internal/crypto/header.go, and wire the headers through cmd/encryption-v1.go.
  • Tune cipher chunk size. It comes from github.com/minio/sio defaults; changing it requires backwards-compatibility planning because it changes on-disk layout.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

KMS and encryption – MinIO wiki | Factory