MinIO Security Overview Slack

Server-Side Encryption

MinIO supports two different types of server-side encryption (SSE):

Server-Side Encryption - Preliminaries

Secret Keys

The MinIO server uses an unique, randomly generated secret key per object also known as, Object Encryption Key (OEK). Neither the client-provided SSE-C key nor the KMS-managed key is directly used to en/decrypt an object. Instead, the OEK is stored as part of the object metadata next to the object in an encrypted form. To en/decrypt the OEK another secret key is needed also known as, Key Encryption Key (KEK).

The MinIO server runs a key-derivation algorithm to generate the KEK using a pseudo-random function (PRF):
KEK := PRF(EK, IV, context_values) where:

To summarize for any encrypted object there exists (at least) three different keys:

Content Encryption

The MinIO server uses an authenticated encryption scheme (AEAD) to en/decrypt and authenticate the object content. The AEAD is combined with some state to build a Secure Channel. A Secure Channel is a cryptographic construction that ensures confidentiality and integrity of the processed data. In particular the Secure Channel splits the plaintext content into fixed size chunks and en/decrypts each chunk separately using an unique key-nonce combination.

Figure 1 - Secure Channel construction
plaintext   := chunk_0          ||       chunk_1          ||       chunk_2          ||       ...
                 |                         |                         |
                 |                         |                         |
               AEAD <- key, nonce + 0    AEAD <- key, nonce + 1    AEAD <- key, nonce + 2    ...
                 |                         |                         |
                 |                         |                         |
ciphertext  := sealed_chunk_0   ||       sealed_chunk_1   ||       sealed_chunk_2   ||       ...

In case of a S3 multi-part operation each part is en/decrypted with the scheme shown in Figure 1. However, for each part an unique secret key is derived from the OEK and the part number using a PRF. So in case of multi-part not the OEK but the output of PRF(OEK, part_id) is used as secret key.

Cryptographic Primitives

The SSE schemes described in Secret Keys and Content Encryption are generic over the cryptographic primitives. However, the MinIO server uses the following cryptographic primitive implementations:

Further any secret key (apart from the KMS-generated ones) is 256 bits long. The KMS-generated keys may be 256 bits but this depends on the KMS capabilities and configuration.

The Secure Channel splits the object content into chunks of a fixed size of 65536 bytes. The last chunk may be smaller to avoid adding additional overhead and is treated specially to prevent truncation attacks. The nonce value is 96 bits long and generated randomly per object / multi-part part. The Secure Channel supports plaintexts up to 65536 * 2^32 = 256 TiB.


The MinIO server generates unique keys and other cryptographic values using a cryptographically secure pseudo-random number generator (CSPRNG). However, in the context of SSE, the MinIO server does not require that the CSPRNG generates values that are indistinguishable from truly random bit strings. Instead, it is sufficient if the generated values are unique - which is a weaker requirement. Nevertheless other parts - for example the TLS-stack - may require that CSPRNG-generated values are indistinguishable from truly random bit strings.

Server-Side Encryption with client-provided Keys

SSE-C allows an S3 client to en/decrypt an object at the MinIO server. Therefore the S3 client sends a secret key as part of the HTTP request. This secret key is never stored by the MinIO server and only resides in RAM during the en/decryption process.

MinIO does not assume or require that the client-provided key is unique. It may be used for multiple objects or buckets. Especially a single client-provided key may be used for all objects - even though all objects must be treated as compromised if that key is ever compromised.

Key rotation

S3 clients can change the client-provided key of an existing object. Therefore an S3 client must perform a S3 COPY operation where the copy source and destination are equal. Further the COPY request headers must contain the current and the new client key:

Such a special COPY request is also known as S3 SSE-C key rotation.

Server-Side Encryption with a KMS

SSE-S3 allows an S3 client to en/decrypt an object at the MinIO server using a KMS. The MinIO
server only assumes that the KMS provides two services:

More details about supported KMS implementations and configuration can be found at the KMS guide.

The MinIO server requests a new data key from the KMS for each uploaded object and uses that data key as EK. Additionally it stores the encrypted form of the data key and the master key ID as part of the object metadata. The plain data only resides in RAM during the en/decryption process. The MinIO server does not store any SSE-related key at the KMS. Instead the KMS is treated as trusted component that performs key sealing/unsealing operations to build a key hierarchy:

Figure 2 - KMS key hierarchy

                                                          CMK (master key)
                       |                                   |                                   |
               +-------+----------------+          +-------+----------------+                 ...
               |  EK_1 | EK_1_encrypted |          |  EK_2 | EK_2_encrypted |
               +---+----------+---------+          +---+----------+---------+
                   |          |                        |          |
                   |          |                        |          |
               +---+---+      |                    +---+---+      |
               | KEK_1 |      |                    | KEK_2 |      |
               +---+---+      |                    +---+---+      |
                   |          |                        |          |
                   |          |                        |          |
               +---+---+      |                    +---+---+      |
               | OEK_1 |      |                    | OEK_2 |      |
               +---+---+      |                    +---+---+      |
                              |                                   |
                              |                                   |
                              |                                   |
                    +---------+---------+               +---------+---------+
                    | object_metadata_1 |               | object_metadata_2 |
                    +-------------------+               +-------------------+

Key rotation - Basic Operation

The MinIO server supports key rotation for SSE-S3 encrypted objects. The minio server decrypts the OEK using the current encrypted data key and the master key ID of the object metadata. If this succeeds, the server requests a new data key from the KMS using the master key ID of the current MinIO KMS configuration and re-wraps the OEK with a new KEK derived from the new data key / EK:

Figure 3 - KMS data key rotation
              object metadata                                         KMS
                    |                                                  |
                    |                     +----------------+        1a |  +-------+
                    |-------------------->| EK_1_encrypted |-----------|->| CMK_1 |
                    |                     +----------------+           |  +---+---+
                    |                                                  |      |
                    |              +---------------+       +------+ 1b |      |
                    |------------->| OEK_encrypted |       | EK_1 |<---|------+
                    |              +-------+-------+       +------+    |
                    |                       \             /            |
                    |                        \___  2  ___/             |
                    |                            \___/                 |
                    |                              |                   |
                    |                           +--+--+                |
                    |                           | OEK |                |  +-------+
                    |                           +--+--+                |  | CMK_2 |
                    |                              |                   |  +---+---+
                    |                              |                   |      |
                    | 5     +----------------+     |4      +------+ 3a |      |
                    |<------| OEK_encrypted' |<----+-------| EK_2 |<---|------+
                    |       +----------------+             +------+    |      |
                    |                    +----------------+         3b |      |
                    |<-------------------| EK_2_encrypted |<-----------|------+
                    |                    +----------------+            |
                    |                                                  |

1a) Send encrypted data key and master key ID to KMS.
1b) Receive decrypted data key.
2)  Decrypt encrypted object key with the KEK derived from the data key.
3a) Receive new plain data key from the KMS using the master key ID of the server config.
3b) Receive encrypted form of the data key from the KMS.
4)  Derive a new KEK from the new data key and re-encrypt the OEK with it.
5)  Store the encrypted OEK encrypted data key and master key ID in object metadata.

Only the root/admin user can perform an SSE-S3 key rotation using the Admin-API via mc. For more details about how to perform key management operations using the CLI refer to mc admin guide or run mc admin kms key.

Secure Erasure and Locking

The MinIO server requires an available KMS to en/decrypt SSE-S3 encrypted objects. Therefore it is possible to erase or lock some or all encrypted objects. For example in case of a detected attack or other emergency situations the following actions can be taken: