# Encrypt the objects in a bucket

> Turn on default encryption so every new object in a bucket is encrypted as it is written, or encrypt single objects with a key that only you hold.

Source: https://www.coritan.com/docs/object-storage/encryption/

In the dashboard:

- /dashboard/storage/…/buckets/…/settings: https://www.coritan.com/dashboard/storage

Object Storage can encrypt your objects as it stores them. There are two ways, and you can use both on one bucket:

- **Default encryption** encrypts every object written to a bucket with AES-256. We hold the key. You turn it on once per bucket and change nothing else.
- *Your own key* (SSE-C) encrypts one object with a 256-bit key that you send with the upload. You hold the key, and nobody can read the object without it.

## Before you begin

- Sign in to the [dashboard](https://www.coritan.com/dashboard/storage) and open the service. The service must be `active` to change a bucket's encryption.
- Default encryption has to be available. Until we turn it on, the card says `Default encryption is not available yet. We are getting it ready and will turn it on soon.` Your own key works at any time.

## How default encryption works {#how-it-works}

With default encryption on, a bucket encrypts every object written to it, whether you upload it in one request, in parts, or copy it in from another bucket. We encrypt it before we store it and decrypt it when you read it. Reading, listing, copying, presigned URLs and the bucket's public URL work as they did, and your access keys need no change.

Encryption applies to objects written after you turn it on. Objects that are already in the bucket stay as they are, encrypted or not. Turning it off works the same way: new objects are not encrypted, and the encrypted ones stay readable.

We hold the key that opens these objects. Default encryption protects the stored data. It does not hide an object from a key that can read the bucket. For a key that only you hold, use [your own key](#your-own-key).

Default encryption has no charge of its own. Storage and requests are billed as for any object ([How Object Storage is billed](/docs/object-storage/usage-and-billing/)).

## Turn on default encryption {#turn-on}

1. Open the service, select the **Buckets** tab, then select the bucket.
2. Select the **Settings** tab.
3. On the **Default encryption** card, in **Encrypt new objects**, select **Turn on encryption…**.
4. Read the dialog, then select **Turn on encryption**.

The row's badge changes from **Off** to **On**, and a message says that new objects in the bucket are encrypted. The change applies within seconds.

To stop encrypting new objects, select **Turn off encryption…**, then **Turn off encryption**. Objects that are already encrypted stay encrypted.

If the badge reads **Not available yet**, there is no button. The row gives the reason: encryption is not turned on for the platform yet, or the service is not active.

## Encrypt objects that are already in the bucket {#existing-objects}

Copy an object over itself to encrypt it with the bucket's default. S3 asks for something to change in a copy onto itself, so replace the metadata:

```python title="Encrypt an existing object with boto3"
s3.copy_object(
    Bucket="u7-assets",
    Key="reports/2026-09.pdf",
    CopySource={"Bucket": "u7-assets", "Key": "reports/2026-09.pdf"},
    MetadataDirective="REPLACE",
    Metadata={"encrypted": "yes"},
)
```

Uploading the object again has the same result. A copy into a bucket with default encryption on is encrypted, and a copy out to a bucket without it is not.

## Check that an object is encrypted {#check}

`HeadObject` and `GetObject` answer `ServerSideEncryption: AES256` for an object written while default encryption was on:

```bash title="Read an object's encryption with the AWS CLI"
aws s3api head-object --bucket u7-assets --key reports/2026-09.pdf \
  --endpoint-url https://s3.fra.coritan.com:7337 --query ServerSideEncryption
```

```text
"AES256"
```

An object written before you turned encryption on answers nothing for it.

## Your own key (SSE-C) {#your-own-key}

With SSE-C you send a 256-bit key with each upload and each read. We use the key only while we handle the request, and we never store it. The key does not need default encryption, and it works with encryption on or off. It needs no setup.

Send these headers with the upload and with every read (`GetObject` and `HeadObject`). An S3 library sets them when you pass the key. In boto3, pass `SSECustomerAlgorithm="AES256"` and `SSECustomerKey` to `put_object`, `get_object` and `head_object`.

| Header | Value |
| --- | --- |
| `x-amz-server-side-encryption-customer-algorithm` | `AES256` |
| `x-amz-server-side-encryption-customer-key` | Your key, 32 bytes, as base64 |
| `x-amz-server-side-encryption-customer-key-MD5` | The MD5 digest of the key, as base64 |

What you get back:

| Request | Answer |
| --- | --- |
| `PutObject` with the key | `200`, with `SSECustomerAlgorithm` `AES256` and the key's MD5 in the answer. Needs a read and write key. |
| `GetObject` or `HeadObject` with the same key | `200`. A read only key works too. |
| `GetObject` without the key | `400` `InvalidArgument`. |
| `GetObject` with another key | `403` `AccessDenied`. |

> [!WARNING]
> Keep the key somewhere safe. If you lose it, nobody can read the object again, and we cannot recover it for you.

## Change encryption with the API {#with-the-api}

Read a bucket's setting. `available` says whether you can turn encryption on now, and `reason` says why not when it is `false`:

```bash title="Read a bucket's encryption"
curl https://api.coritan.com/api/v1/client/object-storage/42/buckets/17/encryption \
  -H "Authorization: Bearer $CORITAN_TOKEN"
```

```json
{
  "bucket_id": 17,
  "enabled": false,
  "algorithm": null,
  "available": true,
  "reason": null
}
```

Turn it on or off with `enabled`:

```bash title="Turn on default encryption"
curl -X PUT https://api.coritan.com/api/v1/client/object-storage/42/buckets/17/encryption \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"enabled": true}'
```

The answer has the same shape, with `enabled` set to `true` and `algorithm` set to `AES256`.

Before you create a bucket, `GET /api/v1/client/object-storage/{service_id}/encryption` tells you whether encryption is available for the service. It answers `available`, `reason` and `algorithm`.

| Answer | Meaning |
| --- | --- |
| `404` | The service or the bucket is not yours. |
| `409` | You asked to turn encryption on and it is not available yet, or the service is not active. The message says which. |
| `422` | `enabled` is missing or is not `true` or `false`. |
| `429` | You made 60 changes in an hour. Wait for the time in the `Retry-After` header. |

A signed S3 request cannot change a bucket's encryption. `PutBucketEncryption` answers `403` `AccessDenied` ([Bucket settings](/docs/object-storage/s3-compatibility/#bucket-settings)).

## Troubleshooting

`500` `InternalError` on an upload that asks for AES256
: A tool or a setting adds `x-amz-server-side-encryption: AES256` to uploads (`aws s3 cp --sse AES256` does). Default encryption is not available yet, so we cannot honour the request. Remove the setting and upload again. When the card reads **On** or **Off** instead of **Not available yet**, the same upload works.

`400` `InvalidArgument` when you read an object
: The object was uploaded with your own key. Send the key and its headers with the read.

`403` `AccessDenied` when you read an object with a key
: The key is not the one the object was uploaded with.

An object does not answer `ServerSideEncryption`
: It was written before you turned encryption on. [Copy it over itself](#existing-objects).

## Related

- [Create and delete buckets](/docs/object-storage/buckets/)
- [S3 API compatibility](/docs/object-storage/s3-compatibility/)
- [Create and revoke access keys](/docs/object-storage/access-keys/)
- [Keep earlier versions of objects](/docs/object-storage/versioning/)

## API

- `GET /api/v1/client/object-storage/{service_id}/encryption`: Get service encryption (https://www.coritan.com/docs/api/reference/client/object-storage/object-storage/#op-get-api-v1-client-object-storage-service-id-encryption)
- `GET /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/encryption`: Get bucket encryption (https://www.coritan.com/docs/api/reference/client/object-storage/object-storage-buckets/#op-get-api-v1-client-object-storage-service-id-buckets-bucket-id-encryption)
- `PUT /api/v1/client/object-storage/{service_id}/buckets/{bucket_id}/encryption`: Turn default encryption on or off for the bucket (https://www.coritan.com/docs/api/reference/client/object-storage/object-storage-buckets/#op-put-api-v1-client-object-storage-service-id-buckets-bucket-id-encryption)
