WebDisk
Object Storage

Шифрування в S3: SSE-S3, SSE-KMS і SSE-C – хто тримає ключ до ваших файлів?

Data publikacji:

Блог WebDisk · категорія: Безпека · час читання: ~12 хвилин

Коротко:- SSE-S3 – ключами керує об’єктне сховище; вмикаєте й забуваєте.- SSE-KMS – ключі живуть у зовнішньому сейфі (KMS); ви отримуєте аудит, ротацію та розділення прав.- SSE-C – ключ передаєте з кожним запитом, сервер його не зберігає; максимум контролю та повна відповідальність. >Не працюєте з терміналом? Можете спокійно пропустити приклади коду – порівняльна таблиця та розділ про WebDisk Files і Send дають повну картину.

Коли ви завантажуєте файл у хмару, у фоні відбувається дещо, про що ми рідко думаємо: ваші дані опиняються на фізичних дисках у чиїйсь серверній. Що станеться, якщо такий диск замінять під час сервісного обслуговування і він покине серверну? Або якщо резервна копія потрапить у чужі руки? Відповіддю на ці питання є шифрування даних у стані спокою (encryption at rest) – а у світі протоколу S3, яким послуговується й наша платформа, воно має три стандартні варіанти: SSE-S3, SSE-KMS і SSE-C.

Вони відрізняються однією, але фундаментальною деталлю: тим, хто генерує, зберігає та контролює ключ шифрування. У цій статті пояснюємо, як працює кожен із варіантів, показуємо на прикладах, як скористатися ними самостійно, і описуємо, як ми використовуємо їх на практиці в послугах WebDisk Files і WebDisk Send.

Дві різні проблеми: дані в дорозі та дані у стані спокою

Перш ніж перейти до SSE, впорядкуймо поняття, бо «шифрування» буває мішком, до якого вкидають різні речі:

  • Шифрування в транзиті захищає дані в дорозі між вами та сервером. Це завдання TLS – тієї самої технології, що стоїть за замочком у браузері. Без TLS хтось, хто прослуховує мережу (напр. у відкритому Wi-Fi), міг би перехопити файл, що передається.
  • Шифрування у стані спокою захищає дані, які лежать на дисках. Навіть якщо хтось фізично заволодіє носієм або сирими файлами із сервера, він побачить лише криптографічний шум.

Ці механізми доповнюють одне одного, а не заміняють. Уся комунікація з послугами WebDisk завжди йде через TLS – це обов’язковий шар. Шифрування у стані спокою – це другий шар, і саме про нього ця стаття.

Server-Side Encryption (SSE) означає, що шифруванням займається сервер: дані приїжджають через TLS, сервер шифрує їх перед записом на диск, а під час завантаження розшифровує. Альтернативою є шифрування на боці клієнта (client-side / end-to-end), де сервер від початку до кінця бачить виключно шифротекст – зашифровану, нечитабельну форму даних. Ми повернемося до цієї відмінності у FAQ, бо вона важлива для чесної оцінки гарантій.

Як сервер шифрує: конверт у конверті

Усі три варіанти шифрують дані одним і тим самим перевіреним алгоритмом: AES-256 – симетричним блоковим шифром, який за коректної реалізації перебуває поза досяжністю будь-якої відомої атаки перебором. По-справжньому цікаве те, що відбувається з ключами.

Перші два варіанти – SSE-S3 і SSE-KMS – використовують так зване конвертне шифрування (envelope encryption):

  1. Кожен об’єкт (файл) шифрується власним, одноразовим ключем даних (DEK – data encryption key).
  2. Ключ даних, своєю чергою, зашифрований головним ключем (KEK – key encryption key) і лише в такій зашифрованій формі записаний у метаданих об’єкта.
  3. Головний ключ ніколи не лежить поруч із даними – а те, де він живе і хто ним керує, відрізняє SSE-S3 від SSE-KMS.

Завдяки конверту компрометація одного ключа даних відкриває один файл, а не весь архів; ротація головного ключа також не вимагає повторного шифрування петабайтів даних – достатньо перешифрувати невеликі ключі даних.

SSE-C працює інакше: ключ, наданий клієнтом, шифрує об’єкт безпосередньо. Сервер не генерує ключа даних і не записує жодного загорнутого ключа – зберігає виключно хеш ключа, щоб під час наступних запитів перевірити, що надано той самий ключ.

З перспективи користувача S3 вибір варіанта зводиться до заголовків HTTP, які надсилаються під час запису об’єкта (PUT). Читання – окрім SSE-C – прозоре: сервер сам розпізнає, що об’єкт зашифрований, і розшифровує його під час завантаження, якщо тільки ви маєте право доступу до об’єкта (а у варіанті SSE-KMS – також право використання ключа в KMS).

Перш ніж почати: конфігурація клієнта. Приклади використовують офіційний клієнт aws CLI, який працює з будь-яким сховищем, сумісним із S3. Вам потрібна пара ключів доступу (access key + secret key) від вашого постачальника – у послугах WebDisk ви знайдете їх у панелі. Налаштуйте їх один раз: >

aws configure # вкажіть access key і secret key (регіон: напр. us-east-1)

>

Якщо ваше сховище не в AWS, кожну команду доповніть endpoint-ом постачальника: >

aws --endpoint-url https://s3.twoj-dostawca.example s3 ls

>

Для читабельності в подальших прикладах ми опускаємо --endpoint-url – пам’ятайте про нього, якщо не користуєтеся AWS.

SSE-S3 – сервер керує всім

Це варіант «увімкни й забудь». Ключі даних і головний ключ генерує, зберігає та ротує саме об’єктне сховище. Користувач не бачить жодного ключа – він лише декларує намір шифрувати.

Технічно достатньо одного заголовка під час запису:

x-amz-server-side-encryption: AES256

На практиці його рідко додають вручну до кожного запиту. Зручнішим є шифрування бакета за замовчуванням (бакет – це контейнер для об’єктів у S3 – відповідник диска чи спільного ресурсу; у послугах WebDisk ми називаємо його сховищем). Від моменту ввімкнення кожен новозаписаний об’єкт шифрується автоматично, незалежно від того, чи просив про це клієнт. Саме так, зрештою, працює сьогодні AWS – із січня 2023 року всі нові об’єкти в S3 там за замовчуванням шифруються SSE-S3. У Ceph RGW (рушії нашої платформи) шифрування бакета за замовчуванням налаштовується ідентичним викликом API.

# окремий файл із явним запитом на шифрування
aws s3 cp raport.pdf s3://moj-bucket/ --sse AES256

# або раз і назавжди: шифрування всього бакета за замовчуванням
aws s3api put-bucket-encryption --bucket moj-bucket \
  --server-side-encryption-configuration \
  '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]}'

# перевірка: чи об’єкт зашифровано?
aws s3api head-object --bucket moj-bucket --key raport.pdf
# у відповіді: "ServerSideEncryption": "AES256"

Що дає SSE-S3: захист від «фізичних» сценаріїв – винесений диск, носій після аварії, сирі файли, скопійовані з файлової системи сервера, стають непридатними.

Чого не дає: захисту від компрометації облікового запису. Хто має право читати об’єкт, той отримує його розшифрованим – сервер робить це автоматично. Викрадені ключі API означають доступ до читабельних даних, точно так само, як і без шифрування. Це не вада реалізації, а межа моделі: SSE-S3 захищає носії, а не обліковий запис.

SSE-KMS – ключі, винесені до сейфа

SSE-KMS працює як SSE-S3, але головний ключ належить уже не об’єктному сховищу, а зовнішній службі керування ключами (KMS – Key Management Service). Об’єктне сховище мусить під час кожної операції попросити KMS розшифрувати ключ даних – і тут з’являються три практичні переваги:

  1. Розділення прав. Доступ до об’єкта і доступ до ключа – це два незалежні рішення. Можна відібрати право використання ключа – і дані стають нечитабельними навіть для того, хто досі має доступ до бакета.
  2. Аудит. Кожне використання ключа залишає слід у логах KMS: хто, коли, для чого. Для відповідності (GDPR, ISO 27001) це часто жорстка вимога.
  3. Життєвий цикл ключа. Ротація, вимкнення, анулювання – керовані централізовано, для кожного ключа окремо, без втручання в дані. Багато впроваджень KMS дозволяють також принести власний матеріал ключа (BYOK – bring your own key).

Під час запису декларується варіант aws:kms і опційно ідентифікатор ключа:

x-amz-server-side-encryption: aws:kms
x-amz-server-side-encryption-aws-kms-key-id: <ідентифікатор-ключа>

# в AWS спершу створюєте ключ у службі KMS і надаєте йому псевдонім
aws kms create-key --description "Ключ для корпоративних документів"
aws kms create-alias --alias-name alias/moj-klucz-firmowy \
  --target-key-id <KeyId-з-попередньої-команди>

# вивантаження із SSE-KMS, що вказує на конкретний ключ
aws s3 cp raport.pdf s3://moj-bucket/ \
  --sse aws:kms --sse-kms-key-id alias/moj-klucz-firmowy

В AWS роль KMS виконує служба AWS KMS. У світі Ceph RGW бекендом KMS може бути, зокрема, HashiCorp Vault або його відкритий форк OpenBao – і саме цей шлях ми обрали у WebDisk: ключі шифрування живуть в окремому, ізольованому криптографічному сейфі, а об’єктні сервери отримують їх на вимогу, автентифікованим каналом, без записування на диск поруч із даними. Ідентифікатор ключа із заголовка відповідає тоді назві ключа в сейфі.

У послугах WebDisk SSE-KMS працює «під капотом» платформи – це не опція, яку ви вмикаєте самостійно. Вибори, які ми віддаємо прямо в руки користувача, – це SSE-S3 (шифровані сховища у Files) і SSE-C (ключ організації у Files) – про обидва докладніше за хвилину.

Компроміс: SSE-KMS – це додаткова рухома частина (KMS мусить бути доступним, щоб дані можна було читати) і накладні витрати на комунікацію із сейфом. Натомість ми отримуємо аудит, централізоване керування та можливість «відрізати» дані одним рухом.

SSE-C – ключ приносите ви

Третій варіант міняє ролі місцями: ключ генерує і зберігає клієнт, а сервер лише виконує шифрування. Під час кожного запиту – запису й читання – клієнт надсилає свій 256-бітний ключ у заголовках:

x-amz-server-side-encryption-customer-algorithm: AES256
x-amz-server-side-encryption-customer-key: <ключ, закодований у base64>
x-amz-server-side-encryption-customer-key-MD5: <сума MD5 ключа, base64>

Сервер використовує ключ для шифрування об’єкта, після чого ключ відкидає – ніде його не записує. Запам’ятовує лише криптографічний відбиток ключа (AWS S3 – випадково посолений HMAC, Ceph RGW – суму MD5 ключа): достатній, щоб під час наступних запитів розпізнати, що надано той самий ключ, але непридатний для його відтворення.

Наслідки серйозні, і їх треба розуміти перед використанням:

  • Втрата ключа = втрата даних. Безповоротно. Постачальник не має жодної копії і жодної процедури відновлення – це не маркетингова декларація, а властивість конструкції.
  • TLS обов’язковий. Ключ мандрує в заголовку HTTP, тому сервер відхиляє запити SSE-C, що надходять без шифрованого з’єднання (у Ceph RGW за цим стежить опція rgw_crypt_require_ssl, увімкнена за замовчуванням).
  • Звичайних посилань уже недостатньо. Більшість механізмів надання доступу до файлів із S3 спирається на так звані presigned URL – посилання із вбудованим, обмеженим у часі підписом прав, завдяки якому можна завантажити об’єкт без входу в систему. Presigned URL підписує запит, але заголовків із ключем не пронесе – той, хто завантажує, все одно мусить знати ключ. Браузер, який отримав саме лише посилання, не завантажить об’єкт SSE-C. Застосунки мусять обробити цей випадок окремо (за хвилину покажемо, як це робить Files).

Приклад із нуля, з використанням openssl та aws CLI:

# 1. згенеруйте 32-байтовий (256-бітний) ключ і сховайте його в безпечному місці
openssl rand -out sse-c.key 32

# 2. вивантаження із SSE-C
aws s3 cp tajne.pdf s3://moj-bucket/tajne.pdf \
  --sse-c AES256 --sse-c-key fileb://sse-c.key

# 3. завантаження – вимагає ТОГО САМОГО ключа
aws s3 cp s3://moj-bucket/tajne.pdf pobrane.pdf \
  --sse-c AES256 --sse-c-key fileb://sse-c.key

# 4. спроба завантажити без ключа завершується помилкою 400
aws s3 cp s3://moj-bucket/tajne.pdf test.pdf

Увага для користувачів AWS S3: із квітня 2026 року нові бакети (а також наявні в облікових записах, які не мали об’єктів SSE-C) мають запис SSE-C заблокований за замовчуванням – вивантаження із заголовками SSE-C поверне помилку 403 AccessDenied. Розблокуєте його одноразово: >

aws s3api put-bucket-encryption --bucket moj-bucket \
  --server-side-encryption-configuration \
  '{"Rules":[{"BlockedEncryptionTypes":{"EncryptionType":["NONE"]}}]}'

>

Читання раніше записаних об’єктів SSE-C працює без змін. На сховищах Ceph RGW – зокрема в послугах WebDisk – SSE-C працює одразу, без цього кроку.

Те саме програмно на Python (boto3 сам закодує ключ у base64 і додасть суму MD5):

import boto3, os

s3 = boto3.client("s3", endpoint_url="https://s3.twoj-dostawca.example")

key = os.urandom(32) # 256-бітний ключ – збережіть його безпечно!

with open("tajne.pdf", "rb") as f:
    s3.put_object(
        Bucket="moj-bucket", Key="tajne.pdf", Body=f,
        SSECustomerAlgorithm="AES256",
        SSECustomerKey=key,
    )

obj = s3.get_object(
    Bucket="moj-bucket", Key="tajne.pdf",
    SSECustomerAlgorithm="AES256",
    SSECustomerKey=key,
)

Важливий нюанс задля повної чесності: при SSE-C сервер бачить ключ і вміст файлу під час обробки запиту (у пам’яті, на час операції) – натомість ніколи не бачить їх після її завершення. Якщо вимогою є, щоб сервер не бачив вмісту в жоден момент, потрібне шифрування на боці клієнта, а не SSE.

Три варіанти стисло

  • Хто генерує головний ключ – SSE-S3: об’єктне сховище · SSE-KMS: служба KMS · SSE-C: клієнт
  • Де він зберігається – SSE-S3: усередині сховища · SSE-KMS: у KMS (сейф поза сховищем) · SSE-C: виключно у клієнта
  • Що зберігає сервер – SSE-S3: усе · SSE-KMS: зашифровані ключі даних · SSE-C: шифротекст + хеш ключа
  • Втрата ключа на боці клієнта – SSE-S3: неможлива · SSE-KMS: неможлива · SSE-C: втрата даних
  • Аудит і ротація ключів – SSE-S3: внутрішні, автоматичні · SSE-KMS: централізовані, видимі, для кожного ключа окремо · SSE-C: цілком на боці клієнта
  • Зусилля користувача – SSE-S3: нульові · SSE-KMS: невеликі (керування ключем у KMS) · SSE-C: великі (повна відповідальність)
  • Типовий сценарій – SSE-S3: розумний стандарт за замовчуванням · SSE-KMS: комплаєнс, аудит, BYOK · SSE-C: максимум контролю над ключем Просте правило вибору: SSE-S3, коли ви просто хочете мати зашифровані дані у стані спокою і нічим не керувати; SSE-KMS, коли аудитор питає «хто і коли використав ключ» або політика компанії вимагає контролю життєвого циклу ключів; SSE-C, коли ключ має бути виключно у ваших руках – і ви готові понести наслідки цього.

Як ми це робимо у WebDisk: Files і Send

Теорія набуває сенсу, коли її видно в робочому продукті. Дві наші файлові послуги свідомо розташовані на двох кінцях спектра «простота ↔ контроль».

WebDisk Files – шари на вибір

Files – це наша платформа безпечного зберігання файлів для компаній. Шифрування в ній укладене шарами, а два механізми SSE з цієї статті виступають у ролях, які пасують їм найкраще:

  • SSE-S3 на рівні сховища. Створюючи додаткове сховище (бакет), можна одним перемикачем увімкнути його постійне шифрування. Відтоді кожен файл – завантажений із панелі, через десктопний застосунок чи в межах надання доступу – шифрується автоматично, у джерелі, завдяки шифруванню бакета за замовчуванням. Рішення односпрямоване (сховище не можна «розшифрувати» перемикачем), користувач не керує жодним ключем, а головні ключі не лежать поруч із даними – вони живуть у виділеному криптографічному сейфі (OpenBao), з окремим ключем для кожного сховища.
  • SSE-C на рівні організації. Організація може увімкнути додаткове шифрування вибраних файлів і папок механізмом SSE-C. Важлива відмінність від самостійного SSE-C, описаного вище: ключем тут керує не користувач, а застосунок Files від імені організації – під час увімкнення функції генерується 256-бітний ключ організації, який застосунок зберігає в зашифрованому вигляді, поза шаром об’єктного сховища. Завдяки цьому об’єктне сховище ніколи не фіксує ключ – винесений носій чи компрометація самого шару зберігання не відкривають цих файлів – і водночас організація не несе ризику безповоротної втрати даних: сценарій «загубив ключ – дані втрачено» стосується самостійного використання SSE-C через API, а не цієї функції. Задля чесності треба додати: у цій моделі доступ до ключа має застосунок – а отже, технічно й постачальник; якщо вимогою є, щоб постачальник не міг прочитати вміст у жоден момент, належним інструментом є шифрування на боці клієнта (див. FAQ). Наслідки протоколу SSE-C застосунок обробляє сам: зашифровані файли не можна завантажити звичайним presigned URL (він не переносить заголовків із ключем), тож Files віддає їх через застосунок, стримінгуючи дані після перевірки прав. Підтримку SSE-C має також наш десктопний застосунок для синхронізації папок.
  • Взаємодоповнювані шари. Шифрування захищає конфіденційність, але не захищає від перезапису чи зашифрування файлів програмою-вимагачем на комп’ютері користувача. Тому поряд із SSE Files пропонує версіонування та режим Anty-Ransomware, що спирається на S3 Object Lock у режимі Compliance – блокування незмінності, яке забезпечує шар об’єктного сховища і яке стійке навіть до компрометації самого застосунку. Повна картина безпеки – це завжди сума шарів, а не один механізм.

WebDisk Send – безпека без інструкції з експлуатації

Send розв’язує іншу проблему: «маю великий файл, хочу комусь його надіслати, вже». Проєктуючи його, ми свідомо не перенесли опцію шифрування для окремого файлу з Files – бо послуга, чия сила в браку конфігурації, не повинна починати розмову з питання про ключі.

Безпека Send спирається на механізми, дібрані під сценарій: передавання виключно через TLS, опційний пароль на посилання (контролює доступ до завантаження – це не ключ, що шифрує вміст), ліміт завантажень і дата закінчення терміну дії, а передусім ретенція – файли живуть стільки, скільки передбачає тарифний план, після чого автоматично й остаточно видаляються. Найбезпечніший файл – це той, якого вже немає. Дані при цьому лежать на тій самій об’єктній платформі Ceph, яку ми описали вище – з тим самим операційним тилом.

Якщо вам потрібне шифрування, кероване вами – шифровані сховища, ключ організації, політики ретенції та блокування – це сигнал, що вашим інструментом є Files, а не Send. Цей поділ навмисний.

Часті запитання

Чи сповільнює шифрування у стані спокою вивантаження й завантаження? На практиці ні. Сучасні процесори мають апаратну підтримку AES (AES-NI), а шифрування відбувається потоково. При SSE-KMS додається коротка комунікація із сейфом ключів, знехтувано мала на тлі передавання файлу.

Чи захистить мене SSE-S3, якщо хтось викраде мій пароль або ключі API? Ні – і жоден варіант SSE не має такого завдання. Сервер розшифровує дані кожному, хто має чинні права. Від крадіжки облікових даних захищають сильні паролі, MFA та гігієна ключів API; від наслідків – версіонування та Object Lock.

Я загубив ключ SSE-C. Що тепер? Нічого. Це не сценарій «зверніться до технічної підтримки» – сервер ключа не має, не має його постачальник, не має його ніхто. Дані криптографічно не піддаються відновленню. Тому ключі SSE-C зберігають у менеджері секретів і охоплюють корпоративними процедурами (копії, депозит, спадкоємність). Вищесказане стосується самостійного використання SSE-C через API S3 – у послузі Files ключем SSE-C керує застосунок від імені організації, тож там цього сценарію немає.

Чим SSE відрізняється від наскрізного шифрування (end-to-end)? У SSE шифрує сервер – тож у момент запису й читання він бачить вміст (а при SSE-C також ключ) в оперативній пам’яті. У клієнтському шифруванні (end-to-end) файл шифрується ще на вашому пристрої, і сервер ніколи не бачить ані вмісту, ані ключа – ціною втрати функцій, які вимагають вмісту на боці сервера (перегляди, пошук, ZIP папки). Це дві різні точки на осі довіри; SSE-C – найдалі висунутий варіант із серверного боку.

Як я дізнаюся, що об’єкт зашифровано? aws s3api head-object повертає заголовок x-amz-server-side-encryption (AES256 або aws:kms) – це добрий, швидкий аудит власних бакетів. Увага на SSE-C: head-object для такого об’єкта без надання ключа поверне помилку 400 Bad Request – і саме ця помилка є сигналом, що об’єкт зашифровано клієнтським ключем; заголовок x-amz-server-side-encryption-customer-algorithm ви побачите лише у відповіді на запит із ключем.

Я користуюся rclone, а не aws CLI. Чи можна? Так – rclone підтримує всі три варіанти в конфігурації віддаленого S3: server_side_encryption = AES256 (SSE-S3), server_side_encryption = aws:kms + sse_kms_key_id (SSE-KMS) або sse_customer_algorithm = AES256 + sse_customer_key_base64 (SSE-C).

Підсумок

Шифрування у стані спокою в S3 – це не одна функція, а спектр моделей довіри:

  • SSE-S3 – сервер керує ключами; нуль зусиль, захист носіїв і копій.
  • SSE-KMS – ключі в зовнішньому сейфі; аудит, ротація, розділення прав.
  • SSE-C – ключ виключно у вас; максимум контролю, повна відповідальність.

У WebDisk ми використовуємо ці механізми там, де вони мають сенс: Files віддає вибір у руки адміністратора організації (шифровані сховища SSE-S3, опційне шифрування SSE-C з ключем організації, яким керує застосунок), Send знімає цей вибір із користувача і замикає безпеку ретенцією та паролями на посиланнях, а там, де шифрування ввімкнене, ключі живуть в окремому сейфі – не поруч із даними.

Хочете перевірити це на практиці? Створіть безкоштовний обліковий запис у WebDisk Send або протестуйте WebDisk Files – а якщо маєте питання про шифрування у своїй організації, напишіть нам.


Стаття є частиною циклу про безпеку даних у послугах WebDisk. Усі приклади ви виконаєте на будь-якому сховищі, сумісному з S3 (на AWS S3 приклад SSE-C вимагає одноразового розблокування – див. врізку в розділі про SSE-C); параметр --endpoint-url у aws CLI вказує на endpoint вашого постачальника.

Шифрування в S3: SSE-S3, SSE-KMS і SSE-C – хто тримає ключ д | WebDisk