

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 搭配客戶提供的金鑰 (SSE-C) 使用伺服器端加密
<a name="ServerSideEncryptionCustomerKeys"></a>

伺服器端加密是有關保護靜態資料。伺服器端加密只會加密物件資料，非物件中繼資料。您可以在一般用途儲存貯體中使用伺服器端加密搭配客戶提供的金鑰 (SSE-C)，以使用您自己的加密金鑰來加密資料。如果您提供的加密金鑰作為請求的一部分，Amazon S3 會在資料寫入磁碟時管理資料加密，以及在您存取物件時管理資料解密。因此，您不需要維護任何程式碼來執行資料加密與解密。您只需要管理自己提供的加密金鑰即可。

Amazon S3 中的大多數現代使用案例都不再使用 SSE-C，因為它缺乏使用 Amazon S3 受管金鑰 (SSE-S3) 進行伺服器端加密的靈活性，或使用 AWS KMS 金鑰 (SSE-KMS) 進行伺服器端加密的靈活性。每次與 SSE-C 加密資料互動時，SSE-C 需要提供加密金鑰，因此與從 S3 儲存貯體讀取資料的其他使用者、角色 AWS 或服務共用 SSE-C 金鑰，以便操作您的資料並不切實際。由於對 SSE-KMS 的廣泛支援 AWS，大多數現代工作負載不會使用 SSE-C 加密，因為它缺乏 SSE-KMS 的靈活性。若要進一步了解 SSE-KMS，請參閱 [搭配 AWS KMS 金鑰使用伺服器端加密 (SSE-KMS)](UsingKMSEncryption.md)。

如果您想要防止 SSE-C 加密用於寫入儲存貯體的物件，您可以在變更儲存貯體的預設加密組態時封鎖 SSE-C 加密。當一般用途儲存貯體封鎖 SSE-C `CopyObject`時，任何指定 SSE-C 加密的 `PutObject`、`PostObject`、、分段上傳或複寫請求都會遭到拒絕，並顯示`HTTP 403 AccessDenied`錯誤。若要進一步了解如何封鎖 SSE-C，請參閱 [封鎖或取消封鎖一般用途儲存貯體的 SSE-C](blocking-unblocking-s3-c-encryption-gpb.md)。

使用 SSE-C 無須額外付費。不過，請求設定和使用 SSE-C 會產生標準的 Amazon S3 請求費用。如需定價的資訊，請參閱 [Amazon S3 定價](https://aws.amazon.com/s3/pricing/)。

**重要**  
如 [2025 年 11 月 19 日所宣布](https://aws.amazon.com/blogs/storage/advanced-notice-amazon-s3-to-disable-the-use-of-sse-c-encryption-by-default-for-all-new-buckets-and-select-existing-buckets-in-april-2026/)，Amazon Simple Storage Service 正在部署新的預設儲存貯體安全設定，以針對所有新的一般用途儲存貯體自動停用使用客戶提供金鑰 (SSE-C) 的伺服器端加密。對於 中沒有 SSE-C 加密物件 AWS 帳戶 的現有儲存貯體，Amazon S3 也會為所有新的寫入請求停用 SSE-C。對於 AWS 帳戶 使用 SSE-C 的 ，Amazon S3 不會變更這些帳戶中任何現有儲存貯體的儲存貯體加密組態。此部署從 2026 年 4 月 6 日開始，並將在接下來的幾週內在 37 AWS 個區域完成，包括 AWS 中國和 AWS GovCloud (US) 區域。  
透過這些變更，需要 SSE-C 加密的應用程式在建立新的儲存貯體之後，必須使用 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) API 操作刻意啟用 SSE-C。如需此變更的詳細資訊，請參閱 [新儲存貯體的預設 SSE-C 設定常見問答集](default-s3-c-encryption-setting-faq.md)。

## 使用 SSE-C 之前的考量事項
<a name="considerations-before-using-sse-c"></a>
+ 當您使用 SSE-C 時，S3 永遠不會存放加密金鑰。 每次您希望任何人從 S3 下載 SSE-C 加密資料時，都必須提供加密金鑰。
  + 您會管理哪個加密金鑰用來加密哪個物件的對應。您會負責追蹤針對哪個物件提供哪個加密金鑰。這也表示如果您遺失加密金鑰，則會遺失物件。
  + 由於您是在用戶端管理加密金鑰，因此您會在用戶端管理任何額外的保護措施，例如金鑰輪替。
  + 這種設計可能會讓您難以與其他使用者、角色 AWS 或服務共用 SSE-C 金鑰，以便在資料上操作。由於對 SSE-KMS 的廣泛支援 AWS，大多數現代工作負載不會使用 SSE-C，因為它缺乏 SSE-KMS 的靈活性。若要進一步了解 SSE-KMS，請參閱[使用伺服器端加密搭配 AWS KMS 金鑰 (SSE-KMS)](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingKMSEncryption.html)。
  + 這表示使用 SSE-C 加密的物件無法由 AWS 受管服務原生解密。
+ 在請求上指定 SSE-C 標頭時，您必須使用 HTTPS。
  + 使用 SSE-C 時，Amazon S3 會拒絕所有透過 HTTP 提出的請求。為安全起見，建議任何錯誤地透過 HTTP 傳送的金鑰皆視為已遭洩漏。請捨棄該金鑰，並適當地輪換。
+ 如果您的儲存貯體已啟用版本控制，您上傳的每個物件版本都可以有自己的加密金鑰。您會負責追蹤針對哪個物件版本使用了哪個加密金鑰。
+ Amazon S3 主控台不支援 SSE-C。您無法使用 Amazon S3 主控台上傳物件並指定 SSE-C 加密。您也無法使用主控台來更新使用 SSE-C 存放的現有物件 (例如變更儲存方案或新增中繼資料)。

**Topics**
+ [使用 SSE-C 之前的考量事項](#considerations-before-using-sse-c)
+ [使用客戶提供金鑰 (SSC-C) 指定伺服器端加密](specifying-s3-c-encryption.md)
+ [封鎖或取消封鎖一般用途儲存貯體的 SSE-C](blocking-unblocking-s3-c-encryption-gpb.md)
+ [新儲存貯體的預設 SSE-C 設定常見問答集](default-s3-c-encryption-setting-faq.md)

# 使用客戶提供金鑰 (SSC-C) 指定伺服器端加密
<a name="specifying-s3-c-encryption"></a>

若要搭配客戶提供的金鑰 (SSE-C) 使用伺服器端加密，請先確定 SSE-C 不是 Amazon S3 一般用途儲存貯體的預設加密組態中的封鎖加密類型。如果封鎖，您可以透過更新儲存貯體的預設加密組態來啟用此加密類型。然後，您可以透過傳遞所需的標頭，在上傳請求中使用 SSE-C。請參閱 [支援使用 SSE-C 寫入資料的 Amazon S3 動作](#amazon-s3-actions-that-support-writing-data-with-sse-c)，並確保包含 [SSE-C 物件加密和解密請求所需的 S3 API 標頭](#s3-api-headers-required-for-sse-c-object-encryption-and-decryption-requests)。

當您上傳指定 SSE-C 的物件時，Amazon S3 會使用您提供的加密金鑰，將 AES-256 加密套用至您的資料。然後，Amazon S3 會從記憶體中移除加密金鑰。當您擷取物件時，您必須在要求中提供相同的加密金鑰。Amazon S3 會先驗證您提供的加密金鑰是否相符，然後對物件進行解密，再將物件資料傳回給您。

使用 SSE-C 之前，請確定您已檢閱 [使用 SSE-C 之前的考量事項](ServerSideEncryptionCustomerKeys.md#considerations-before-using-sse-c)。

**注意**  
Amazon S3 不會存放您提供的加密金鑰。相反地，它會存放加密金鑰的隨機雜湊訊息驗證碼 (HMAC) Salt 值，以驗證未來的請求。HMAC Salt 值不可用來衍生加密金鑰的值，或用來對加密物件的內容進行解密。換句話說，如果您遺失加密金鑰，則會遺失物件。

**Topics**
+ [SSE-C 動作和必要標頭](#sse-c-actions-and-required-headers)
+ [強制 SSE-C 加密的儲存貯體政策範例](#example-bucket-policy-to-enforce-sse-c-encryption)
+ [已預先簽章的 URL 和 SSE-C](#ssec-and-presignedurl)
+ [使用 SSE-C 提出請求](#making-requests-with-sse-c)
+ [使用 REST API](#using-rest-api-sse-c)
+ [使用 AWS SDKs為 PUT、GET、頭部和複製操作指定 SSE-C](#sse-c-using-sdks)
+ [使用 AWS SDKs為分段上傳指定 SSE-C](#sse-c-using-sdks-multipart-uploads)

## SSE-C 動作和必要標頭
<a name="sse-c-actions-and-required-headers"></a>

在支援的 S3 APIs 上指定 SSE-C 需要傳遞特定請求參數。

**注意**  
Amazon S3 中的 `PutBucketEncryption` API 用於設定儲存貯體的預設伺服器端加密。不過， `PutBucketEncryption` 不支援啟用 SSE-C 做為儲存貯體的預設加密方法。SSE-C 是一種物件層級加密方法，可讓您在每次物件上傳或下載請求時，將加密金鑰提供給 Amazon S3。Amazon S3 使用此金鑰在請求期間加密或解密物件，然後捨棄金鑰。這表示 SSE-C 是以每個物件為基礎啟用，而不是做為預設儲存貯體設定。

### 支援使用 SSE-C 寫入資料的 Amazon S3 動作
<a name="amazon-s3-actions-that-support-writing-data-with-sse-c"></a>

您可以使用下列 API 操作或動作，在將物件寫入一般用途儲存貯體時，使用客戶提供的金鑰 (SSE-C) 請求伺服器端加密：
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html)

**注意**  
S3 複寫支援使用 SSE-C 加密的物件。如需複寫加密物件的詳細資訊，請參閱 [複寫加密的物件 (SSE-S3、SSE-KMS、DSSE-KMS、SSE-C)](replication-config-for-kms-objects.md)。

### SSE-C 物件加密和解密請求所需的 S3 API 標頭
<a name="s3-api-headers-required-for-sse-c-object-encryption-and-decryption-requests"></a>

您必須提供下列三個 API 標頭，以使用 SSE-C 加密或解密物件：
+ `x-amz-server-side-encryption-customer-algorithm` 使用此標頭來指定加密演算法。標頭值必須為 AES256。
+ `x-amz-server-side-encryption-customer-key` 使用此標頭提供 256 位元的 base64 編碼加密金鑰，讓 Amazon S3 用來加密或解密您的資料。
+ `x-amz-server-side-encryption-customer-key-MD5` 使用此標頭可根據 RFC 1321 提供加密金鑰的 base64 編碼 128 位元 MD5 摘要。Amazon S3 使用此標頭來進行訊息完整性檢查，以確保加密金鑰傳輸無誤。

### 請求複製使用 SSE-C 加密的來源物件所需的 S3 API 標頭
<a name="s3-api-headers-required-for-requests-to-copy-source-objects-encrypted-with-sse-c"></a>

您必須提供下列三個 API 標頭，才能複製使用 SSE-C 加密的來源物件：
+ `x-amz-copy-source-server-side-encryption-customer-algorithm` 包含此標頭來指定 Amazon S3 應該用來解密來源物件的演算法。此值必須是 AES256。
+ `x-amz-copy-source-server-side-encryption-customer-key` 包含此標頭以提供 base64 編碼的加密金鑰，供 Amazon S3 用來解密來源物件。此加密金鑰必須是您建立來源物件時提供給 Amazon S3 的加密金鑰。否則，Amazon S3 無法解密物件。
+ `x-amz-copy-source-server-side-encryption-customer-key-MD5` 包含此標頭，以提供根據 RFC 1321 加密金鑰的 base64 編碼 128 位元 MD5 摘要。

## 強制 SSE-C 加密的儲存貯體政策範例
<a name="example-bucket-policy-to-enforce-sse-c-encryption"></a>

若要針對寫入 Amazon S3 儲存貯體的所有物件要求 SSE-C，您可以使用儲存貯體政策。例如，下列儲存貯體政策拒絕所有不包含請求 SSE-C 之 `x-amz-server-side-encryption-customer-algorithm` 標題請求的上傳物件 (`s3:PutObject`) 許可。

```
{  
"Version":"2012-10-17",		 	 	                      
    "Id": "PutObjectPolicy",  
    "Statement": [  
        {  
"Sid": "RequireSSECObjectUploads",  
            "Effect": "Deny",  
            "Principal": "*",  
            "Action": "s3:PutObject",  
            "Resource": "arn:aws:s3:::amzn-s3-demo-bucket/*",  
            "Condition": {  
            "Null": {  
              "s3:x-amz-server-side-encryption-customer-algorithm": "true"  
                }  
            }  
        }  
    ]  
}
```

**重要**  
如果您使用儲存貯體政策在`s3:PutObject` 上要求 SSE-C，則必須在所有分段上傳請求中包含 `x-amz-server-side-encryption-customer-algorithm` 標頭 (CreateMultipartUpload、UploadPart 和 CompleteMultipartUpload)。

## 已預先簽章的 URL 和 SSE-C
<a name="ssec-and-presignedurl"></a>

您可以產生預先簽章的 URL，其可以用於上傳新的物件、擷取現有的物件或擷取物件中繼資料等操作。預先簽章的 URL 支援如下的 SSE-C：
+ 建立預先簽章的 URL 時，您必須在簽章計算中使用 `x-amz-server-side-encryption-customer-algorithm` 標頭來指定演算法。
+ 使用預先簽章的 URL 來上傳新的物件、擷取現有的物件或只擷取物件中繼資料時，您必須提供用戶端應用程式請求中的所有加密標頭。
**注意**  
針對非 SSE-C 物件，您可以產生預先簽章的 URL，並將該 URL 直接貼入至瀏覽器以存取資料。  
不過，您無法針對 SSE-C 物件執行此操作，因為除了預先簽章的 URL 之外，您亦須包含 SSE-C 物件專屬的 HTTP 標頭。因此，您只能以程式設計方式針對 SSE-C 物件使用預先簽章的 URL。

如需預先簽章的 URL 詳細資訊，請參閱[使用預先簽章的 URL 來下載和上傳物件](using-presigned-url.md)。

## 使用 SSE-C 提出請求
<a name="making-requests-with-sse-c"></a>

 在使用 REST API 建立物件時，您可以使用客戶提供的金鑰 (SSE-C) 來指定伺服器端加密。使用 SSE-C 時，您必須使用 提供加密金鑰資訊[請求複製使用 SSE-C 加密的來源物件所需的 S3 API 標頭](#s3-api-headers-required-for-requests-to-copy-source-objects-encrypted-with-sse-c)。您可以使用 AWS SDK 包裝函式程式庫將這些標頭新增至您的請求。如果需要，您可以直接在應用程式中進行 Amazon S3 REST API 呼叫。

**重要**  
使用客戶提供的金鑰 (SSE-C) 指定伺服器端加密之前，請確定您的一般用途儲存貯體不會封鎖 SSE-C 加密。如需詳細資訊，請參閱[封鎖或取消封鎖一般用途儲存貯體的 SSE-C](blocking-unblocking-s3-c-encryption-gpb.md)。

**注意**  
您無法使用 Amazon S3 主控台上傳物件並請求 SSE-C。 您也無法使用 主控台來更新 （例如，變更儲存類別或新增中繼資料） 使用 SSE-C 存放的現有物件。 如需詳細資訊，請參閱 [SSE-C 物件加密和解密請求所需的 S3 API 標頭](#s3-api-headers-required-for-sse-c-object-encryption-and-decryption-requests)。

## 使用 REST API
<a name="using-rest-api-sse-c"></a>

### 支援 SSE-C 的 Amazon S3 REST API APIs
<a name="sse-c-supported-apis"></a>

下列 Amazon S3 API 支援伺服器端加密搭配客戶提供的加密金鑰 (SSE-C)。
+ **GET 操作** – 使用 GET API 擷取物件時 (請參閱 [GET 物件](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGET.html))，您可以指定這些請求標頭。
+ **HEAD 操作** – 若要使用 HEAD API 擷取物件中繼資料 (請參閱 [HEAD 物件](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectHEAD.html))，您可以指定這些請求標頭。
+ **PUT 操作** – 使用 PUT API 上傳資料時 (請參閱 [PUT 物件](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html))，您可以指定這些請求標頭。
+ **分段上傳** – 使用分段上傳 API 上傳大型物件時，您可以指定這些標頭。您可以在啟動請求 （請參閱[啟動分段上傳](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadInitiate.html)) 和每個後續分段上傳請求 （請參閱[上傳部分](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPart.html)或 [UploadPartCopy](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPartCopy.html)) 中指定這些標頭。每個部分上傳要求的加密資訊，必須與您在啟動分段上傳要求中所提供的加密資訊相同。
+ **POST 操作** – 使用 POST 操作上傳物件時 (請參閱 [POST 物件](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html))，請提供與表單欄位中相同的資訊，而不是請求標頭。
+ **複製操作** – 當您複製物件 （請參閱 [CopyObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html)) 時，您會同時擁有來源物件和目標物件：
  + 如果您想要指定目標物件的加密類型，您必須提供`x-amz-server-side-encryption `請求標頭。
  + 如果您想要使用 SSE-C 加密目標物件，您必須使用 S3 API 提供加密資訊[SSE-C 物件加密和解密請求所需的 S3 API 標頭](#s3-api-headers-required-for-sse-c-object-encryption-and-decryption-requests)。
  + 如果來源物件是使用 SSE-C 加密，您必須使用 S3 API 標頭 提供加密金鑰資訊[請求複製使用 SSE-C 加密的來源物件所需的 S3 API 標頭](#s3-api-headers-required-for-requests-to-copy-source-objects-encrypted-with-sse-c)。

## 使用 AWS SDKs為 PUT、GET、頭部和複製操作指定 SSE-C
<a name="sse-c-using-sdks"></a>

下列範例說明如何用客戶提供金鑰 (SSE-C)，要求為物件進行伺服器端加密。這些範例會執行下列操作。每個操作示範如何在要求中指定 SSE-C 相關標頭：
+ **放置物件** – 使用客戶提供的加密金鑰上傳物件並請求伺服器端加密。
+ **取得物件** – 下載前一個步驟中所上傳的物件。在此請求中，請您提供在您上傳物件時所提供的相同加密資訊。Amazon S3 需要此資訊來解密物件，才能將物件傳回給您。
+ **取得物件中繼資料** – 擷取物件的中繼資料。請您提供物件建立時，使用的加密資訊。
+ **複製物件** – 建立先前上傳物件的複本。因為來源物件是使用 SSE-C 所存放，所以您必須在複製要求中提供其加密資訊。根據預設，只有在您明確請求加密時，Amazon S3 才會加密物件的複本。此範例指示 Amazon S3 存放加密的物件複本。

------
#### [ Java ]

**注意**  
此範例示範如何以單一操作上傳物件。使用分段上傳 API 上傳大型物件時，請您提供如此範例一樣的加密資訊。如需使用 的分段上傳範例 適用於 Java 的 AWS SDK，請參閱 [使用分段上傳來上傳物件](mpu-upload-object.md)。

新增要求加密資訊，您可包含 `SSECustomerKey` 在您的要求中。如需有關 `SSECustomerKey` 類別的詳細資訊，請參閱 REST API 一節。

如需建立和測試工作範例的說明，請參閱《 適用於 Java 的 AWS SDK 開發人員指南》中的[入門](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/getting-started.html)。

**Example**  

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;

import javax.crypto.KeyGenerator;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class ServerSideEncryptionUsingClientSideEncryptionKey {
    private static SSECustomerKey SSE_KEY;
    private static AmazonS3 S3_CLIENT;
    private static KeyGenerator KEY_GENERATOR;

    public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
        Regions clientRegion = Regions.DEFAULT_REGION;
        String bucketName = "*** Bucket name ***";
        String keyName = "*** Key name ***";
        String uploadFileName = "*** File path ***";
        String targetKeyName = "*** Target key name ***";

        // Create an encryption key.
        KEY_GENERATOR = KeyGenerator.getInstance("AES");
        KEY_GENERATOR.init(256, new SecureRandom());
        SSE_KEY = new SSECustomerKey(KEY_GENERATOR.generateKey());

        try {
            S3_CLIENT = AmazonS3ClientBuilder.standard()
                    .withCredentials(new ProfileCredentialsProvider())
                    .withRegion(clientRegion)
                    .build();

            // Upload an object.
            uploadObject(bucketName, keyName, new File(uploadFileName));

            // Download the object.
            downloadObject(bucketName, keyName);

            // Verify that the object is properly encrypted by attempting to retrieve it
            // using the encryption key.
            retrieveObjectMetadata(bucketName, keyName);

            // Copy the object into a new object that also uses SSE-C.
            copyObject(bucketName, keyName, targetKeyName);
        } catch (AmazonServiceException e) {
            // The call was transmitted successfully, but Amazon S3 couldn't process
            // it, so it returned an error response.
            e.printStackTrace();
        } catch (SdkClientException e) {
            // Amazon S3 couldn't be contacted for a response, or the client
            // couldn't parse the response from Amazon S3.
            e.printStackTrace();
        }
    }

    private static void uploadObject(String bucketName, String keyName, File file) {
        PutObjectRequest putRequest = new PutObjectRequest(bucketName, keyName, file).withSSECustomerKey(SSE_KEY);
        S3_CLIENT.putObject(putRequest);
        System.out.println("Object uploaded");
    }

    private static void downloadObject(String bucketName, String keyName) throws IOException {
        GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, keyName).withSSECustomerKey(SSE_KEY);
        S3Object object = S3_CLIENT.getObject(getObjectRequest);

        System.out.println("Object content: ");
        displayTextInputStream(object.getObjectContent());
    }

    private static void retrieveObjectMetadata(String bucketName, String keyName) {
        GetObjectMetadataRequest getMetadataRequest = new GetObjectMetadataRequest(bucketName, keyName)
                .withSSECustomerKey(SSE_KEY);
        ObjectMetadata objectMetadata = S3_CLIENT.getObjectMetadata(getMetadataRequest);
        System.out.println("Metadata retrieved. Object size: " + objectMetadata.getContentLength());
    }

    private static void copyObject(String bucketName, String keyName, String targetKeyName)
            throws NoSuchAlgorithmException {
        // Create a new encryption key for target so that the target is saved using
        // SSE-C.
        SSECustomerKey newSSEKey = new SSECustomerKey(KEY_GENERATOR.generateKey());

        CopyObjectRequest copyRequest = new CopyObjectRequest(bucketName, keyName, bucketName, targetKeyName)
                .withSourceSSECustomerKey(SSE_KEY)
                .withDestinationSSECustomerKey(newSSEKey);

        S3_CLIENT.copyObject(copyRequest);
        System.out.println("Object copied");
    }

    private static void displayTextInputStream(S3ObjectInputStream input) throws IOException {
        // Read one line at a time from the input stream and display each line.
        BufferedReader reader = new BufferedReader(new InputStreamReader(input));
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
        System.out.println();
    }
}
```

------
#### [ .NET ]

**注意**  
如需更說使用分段上傳 API 大型物件的範例，請參閱 [使用分段上傳來上傳物件](mpu-upload-object.md) 和 [使用 AWS SDKs（低階 API)](mpu-upload-object.md#mpu-upload-low-level)。

如需有關設定和執行程式碼範例的資訊，請參閱《[適用於 .NET 的 AWS SDK 開發人員指南》中的適用於 .NET 的 SDK 入門](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)。 *AWS *

**Example**  

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class SSEClientEncryptionKeyObjectOperationsTest
    {
        private const string bucketName = "*** bucket name ***"; 
        private const string keyName = "*** key name for new object created ***"; 
        private const string copyTargetKeyName = "*** key name for object copy ***";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
        private static IAmazonS3 client;

        public static void Main()
        {
            client = new AmazonS3Client(bucketRegion);
            ObjectOpsUsingClientEncryptionKeyAsync().Wait();
        }
        private static async Task ObjectOpsUsingClientEncryptionKeyAsync()
        {
            try
            {
                // Create an encryption key.
                Aes aesEncryption = Aes.Create();
                aesEncryption.KeySize = 256;
                aesEncryption.GenerateKey();
                string base64Key = Convert.ToBase64String(aesEncryption.Key);

                // 1. Upload the object.
                PutObjectRequest putObjectRequest = await UploadObjectAsync(base64Key);
                // 2. Download the object and verify that its contents matches what you uploaded.
                await DownloadObjectAsync(base64Key, putObjectRequest);
                // 3. Get object metadata and verify that the object uses AES-256 encryption.
                await GetObjectMetadataAsync(base64Key);
                // 4. Copy both the source and target objects using server-side encryption with 
                //    a customer-provided encryption key.
                await CopyObjectAsync(aesEncryption, base64Key);
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered ***. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }
        }

        private static async Task<PutObjectRequest> UploadObjectAsync(string base64Key)
        {
            PutObjectRequest putObjectRequest = new PutObjectRequest
            {
                BucketName = bucketName,
                Key = keyName,
                ContentBody = "sample text",
                ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                ServerSideEncryptionCustomerProvidedKey = base64Key
            };
            PutObjectResponse putObjectResponse = await client.PutObjectAsync(putObjectRequest);
            return putObjectRequest;
        }
        private static async Task DownloadObjectAsync(string base64Key, PutObjectRequest putObjectRequest)
        {
            GetObjectRequest getObjectRequest = new GetObjectRequest
            {
                BucketName = bucketName,
                Key = keyName,
                // Provide encryption information for the object stored in Amazon S3.
                ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                ServerSideEncryptionCustomerProvidedKey = base64Key
            };

            using (GetObjectResponse getResponse = await client.GetObjectAsync(getObjectRequest))
            using (StreamReader reader = new StreamReader(getResponse.ResponseStream))
            {
                string content = reader.ReadToEnd();
                if (String.Compare(putObjectRequest.ContentBody, content) == 0)
                    Console.WriteLine("Object content is same as we uploaded");
                else
                    Console.WriteLine("Error...Object content is not same.");

                if (getResponse.ServerSideEncryptionCustomerMethod == ServerSideEncryptionCustomerMethod.AES256)
                    Console.WriteLine("Object encryption method is AES256, same as we set");
                else
                    Console.WriteLine("Error...Object encryption method is not the same as AES256 we set");

                // Assert.AreEqual(putObjectRequest.ContentBody, content);
                // Assert.AreEqual(ServerSideEncryptionCustomerMethod.AES256, getResponse.ServerSideEncryptionCustomerMethod);
            }
        }
        private static async Task GetObjectMetadataAsync(string base64Key)
        {
            GetObjectMetadataRequest getObjectMetadataRequest = new GetObjectMetadataRequest
            {
                BucketName = bucketName,
                Key = keyName,

                // The object stored in Amazon S3 is encrypted, so provide the necessary encryption information.
                ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                ServerSideEncryptionCustomerProvidedKey = base64Key
            };

            GetObjectMetadataResponse getObjectMetadataResponse = await client.GetObjectMetadataAsync(getObjectMetadataRequest);
            Console.WriteLine("The object metadata show encryption method used is: {0}", getObjectMetadataResponse.ServerSideEncryptionCustomerMethod);
            // Assert.AreEqual(ServerSideEncryptionCustomerMethod.AES256, getObjectMetadataResponse.ServerSideEncryptionCustomerMethod);
        }
        private static async Task CopyObjectAsync(Aes aesEncryption, string base64Key)
        {
            aesEncryption.GenerateKey();
            string copyBase64Key = Convert.ToBase64String(aesEncryption.Key);

            CopyObjectRequest copyRequest = new CopyObjectRequest
            {
                SourceBucket = bucketName,
                SourceKey = keyName,
                DestinationBucket = bucketName,
                DestinationKey = copyTargetKeyName,
                // Information about the source object's encryption.
                CopySourceServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                CopySourceServerSideEncryptionCustomerProvidedKey = base64Key,
                // Information about the target object's encryption.
                ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                ServerSideEncryptionCustomerProvidedKey = copyBase64Key
            };
            await client.CopyObjectAsync(copyRequest);
        }
    }
}
```

------

## 使用 AWS SDKs為分段上傳指定 SSE-C
<a name="sse-c-using-sdks-multipart-uploads"></a>

上節中的範例示範如何以 PUT、GET、Head 和 Copy 操作要求經由客戶提供加密金鑰的伺服器端加密 (SSE-C)。本節說明其他支援 SSE-C 的 Amazon S3 API。

------
#### [ Java ]

若要上傳大型物件，您可以使用分段上傳 APIs。如需詳細資訊，請參閱[在 Amazon S3 中使用分段上傳來上傳和複製物件](mpuoverview.md)。您可以使用高階或低階 API 來上傳大型物件。這些 API 支援要求中的加密相關標頭。
+ 使用高階 `TransferManager` API 時，您可以在 中提供加密特定的標頭`PutObjectRequest`。如需詳細資訊，請參閱[使用分段上傳來上傳物件](mpu-upload-object.md)。
+ 使用低階 API 時，請您在 `InitiateMultipartUploadRequest` 提供加密關聯資訊，遵照 `UploadPartRequest` 中每一個的相同加密資訊。您不需要在 `CompleteMultipartUploadRequest` 提供任何加密特定標頭。如需範例，請參閱 [使用 AWS SDKs（低階 API)](mpu-upload-object.md#mpu-upload-low-level)。

下列範例使用 `TransferManager` 建立物件，並示範如何提供 SSE-C 相關資訊。此範例執行下列操作：
+ 使用 `TransferManager.upload()` 方法建立物件。在`PutObjectRequest`執行個體中，您會在請求中提供加密金鑰資訊。Amazon S3 會使用客戶提供的金鑰來加密物件。
+ 呼叫 `TransferManager.copy()` 方法，以建立物件的複本。此範例指示 Amazon S3 使用新的 `SSECustomerKey` 來加密物件複本。因為來源物件使用 SSE-C 加密，所以 `CopyObjectRequest` 也會提供來源物件的加密金鑰，讓 Amazon S3 可以先解密物件，再進行複製。

**Example**  

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.CopyObjectRequest;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.SSECustomerKey;
import com.amazonaws.services.s3.transfer.Copy;
import com.amazonaws.services.s3.transfer.TransferManager;
import com.amazonaws.services.s3.transfer.TransferManagerBuilder;
import com.amazonaws.services.s3.transfer.Upload;

import javax.crypto.KeyGenerator;
import java.io.File;
import java.security.SecureRandom;

public class ServerSideEncryptionCopyObjectUsingHLwithSSEC {

    public static void main(String[] args) throws Exception {
        Regions clientRegion = Regions.DEFAULT_REGION;
        String bucketName = "*** Bucket name ***";
        String fileToUpload = "*** File path ***";
        String keyName = "*** New object key name ***";
        String targetKeyName = "*** Key name for object copy ***";

        try {
            AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                    .withRegion(clientRegion)
                    .withCredentials(new ProfileCredentialsProvider())
                    .build();
            TransferManager tm = TransferManagerBuilder.standard()
                    .withS3Client(s3Client)
                    .build();

            // Create an object from a file.
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, keyName, new File(fileToUpload));

            // Create an encryption key.
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            keyGenerator.init(256, new SecureRandom());
            SSECustomerKey sseCustomerEncryptionKey = new SSECustomerKey(keyGenerator.generateKey());

            // Upload the object. TransferManager uploads asynchronously, so this call
            // returns immediately.
            putObjectRequest.setSSECustomerKey(sseCustomerEncryptionKey);
            Upload upload = tm.upload(putObjectRequest);

            // Optionally, wait for the upload to finish before continuing.
            upload.waitForCompletion();
            System.out.println("Object created.");

            // Copy the object and store the copy using SSE-C with a new key.
            CopyObjectRequest copyObjectRequest = new CopyObjectRequest(bucketName, keyName, bucketName, targetKeyName);
            SSECustomerKey sseTargetObjectEncryptionKey = new SSECustomerKey(keyGenerator.generateKey());
            copyObjectRequest.setSourceSSECustomerKey(sseCustomerEncryptionKey);
            copyObjectRequest.setDestinationSSECustomerKey(sseTargetObjectEncryptionKey);

            // Copy the object. TransferManager copies asynchronously, so this call returns
            // immediately.
            Copy copy = tm.copy(copyObjectRequest);

            // Optionally, wait for the upload to finish before continuing.
            copy.waitForCompletion();
            System.out.println("Copy complete.");
        } catch (AmazonServiceException e) {
            // The call was transmitted successfully, but Amazon S3 couldn't process
            // it, so it returned an error response.
            e.printStackTrace();
        } catch (SdkClientException e) {
            // Amazon S3 couldn't be contacted for a response, or the client
            // couldn't parse the response from Amazon S3.
            e.printStackTrace();
        }
    }
}
```

------
#### [ .NET ]

若要上傳大型物件，您可以使用分段上傳 API （請參閱 [在 Amazon S3 中使用分段上傳來上傳和複製物件](mpuoverview.md))。 AWS SDK for .NET 提供高階或低階 APIs 來上傳大型物件。這些 API 支援要求中的加密相關標頭。
+ 使用高階 `Transfer-Utility `API 時，您在 `TransferUtilityUploadRequest` 所提供的加密特定標頭，如下所示。如需程式碼範例，請參閱 [使用分段上傳來上傳物件](mpu-upload-object.md)。

  ```
  TransferUtilityUploadRequest request = new TransferUtilityUploadRequest()
  {
      FilePath = filePath,
      BucketName = existingBucketName,
      Key = keyName,
      // Provide encryption information.
      ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
      ServerSideEncryptionCustomerProvidedKey = base64Key,
  };
  ```
+ 使用低階 API 時，請提供您在啟動分段上傳要求中的加密相關資訊，後面接著後續分段上傳要求中的相同加密資訊。您不需要在完整的分段上傳要求中提供任何加密特定標頭。如需範例，請參閱 [使用 AWS SDKs（低階 API)](mpu-upload-object.md#mpu-upload-low-level)。

  以下為建立現有大型物件複本的低階分段上傳範例。在此範例中，要複製的物件會使用 SSE-C 存放在 Amazon S3 中，而您也想要使用 SSE-C 儲存目標物件。在此範例中，您要執行以下動作：
  + 提供加密金鑰與相關資訊，以啟動分段上傳要求。
  + 在 `CopyPartRequest` 中提供來源與目標物件加密金鑰以及相關資訊。
  + 擷取物件中繼資料，以取得要複製之來源物件的大小。
  + 將物件分成 5 MB 部分來上傳。  
**Example**  

  ```
  using Amazon;
  using Amazon.S3;
  using Amazon.S3.Model;
  using System;
  using System.Collections.Generic;
  using System.IO;
  using System.Security.Cryptography;
  using System.Threading.Tasks;
  
  namespace Amazon.DocSamples.S3
  {
      class SSECLowLevelMPUcopyObjectTest
      {
          private const string existingBucketName = "*** bucket name ***";
          private const string sourceKeyName      = "*** source object key name ***"; 
          private const string targetKeyName      = "*** key name for the target object ***";
          private const string filePath           = @"*** file path ***";
          // Specify your bucket region (an example region is shown).
          private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
          private static IAmazonS3 s3Client;
          static void Main()
          {
              s3Client = new AmazonS3Client(bucketRegion);
              CopyObjClientEncryptionKeyAsync().Wait();
          }
  
          private static async Task CopyObjClientEncryptionKeyAsync()
          {
              Aes aesEncryption = Aes.Create();
              aesEncryption.KeySize = 256;
              aesEncryption.GenerateKey();
              string base64Key = Convert.ToBase64String(aesEncryption.Key);
  
              await CreateSampleObjUsingClientEncryptionKeyAsync(base64Key, s3Client);
  
              await CopyObjectAsync(s3Client, base64Key);
          }
          private static async Task CopyObjectAsync(IAmazonS3 s3Client, string base64Key)
          {
              List<CopyPartResponse> uploadResponses = new List<CopyPartResponse>();
  
              // 1. Initialize.
              InitiateMultipartUploadRequest initiateRequest = new InitiateMultipartUploadRequest
              {
                  BucketName = existingBucketName,
                  Key = targetKeyName,
                  ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                  ServerSideEncryptionCustomerProvidedKey = base64Key,
              };
  
              InitiateMultipartUploadResponse initResponse =
                  await s3Client.InitiateMultipartUploadAsync(initiateRequest);
  
              // 2. Upload Parts.
              long partSize = 5 * (long)Math.Pow(2, 20); // 5 MB
              long firstByte = 0;
              long lastByte = partSize;
  
              try
              {
                  // First find source object size. Because object is stored encrypted with
                  // customer provided key you need to provide encryption information in your request.
                  GetObjectMetadataRequest getObjectMetadataRequest = new GetObjectMetadataRequest()
                  {
                      BucketName = existingBucketName,
                      Key = sourceKeyName,
                      ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                      ServerSideEncryptionCustomerProvidedKey = base64Key // " * **source object encryption key ***"
                  };
  
                  GetObjectMetadataResponse getObjectMetadataResponse = await s3Client.GetObjectMetadataAsync(getObjectMetadataRequest);
  
                  long filePosition = 0;
                  for (int i = 1; filePosition < getObjectMetadataResponse.ContentLength; i++)
                  {
                      CopyPartRequest copyPartRequest = new CopyPartRequest
                      {
                          UploadId = initResponse.UploadId,
                          // Source.
                          SourceBucket = existingBucketName,
                          SourceKey = sourceKeyName,
                          // Source object is stored using SSE-C. Provide encryption information.
                          CopySourceServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                          CopySourceServerSideEncryptionCustomerProvidedKey = base64Key, //"***source object encryption key ***",
                          FirstByte = firstByte,
                          // If the last part is smaller then our normal part size then use the remaining size.
                          LastByte = lastByte > getObjectMetadataResponse.ContentLength ?
                              getObjectMetadataResponse.ContentLength - 1 : lastByte,
  
                          // Target.
                          DestinationBucket = existingBucketName,
                          DestinationKey = targetKeyName,
                          PartNumber = i,
                          // Encryption information for the target object.
                          ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                          ServerSideEncryptionCustomerProvidedKey = base64Key
                      };
                      uploadResponses.Add(await s3Client.CopyPartAsync(copyPartRequest));
                      filePosition += partSize;
                      firstByte += partSize;
                      lastByte += partSize;
                  }
  
                  // Step 3: complete.
                  CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest
                  {
                      BucketName = existingBucketName,
                      Key = targetKeyName,
                      UploadId = initResponse.UploadId,
                  };
                  completeRequest.AddPartETags(uploadResponses);
  
                  CompleteMultipartUploadResponse completeUploadResponse =
                      await s3Client.CompleteMultipartUploadAsync(completeRequest);
              }
              catch (Exception exception)
              {
                  Console.WriteLine("Exception occurred: {0}", exception.Message);
                  AbortMultipartUploadRequest abortMPURequest = new AbortMultipartUploadRequest
                  {
                      BucketName = existingBucketName,
                      Key = targetKeyName,
                      UploadId = initResponse.UploadId
                  };
                  s3Client.AbortMultipartUpload(abortMPURequest);
              }
          }
          private static async Task CreateSampleObjUsingClientEncryptionKeyAsync(string base64Key, IAmazonS3 s3Client)
          {
              // List to store upload part responses.
              List<UploadPartResponse> uploadResponses = new List<UploadPartResponse>();
  
              // 1. Initialize.
              InitiateMultipartUploadRequest initiateRequest = new InitiateMultipartUploadRequest
              {
                  BucketName = existingBucketName,
                  Key = sourceKeyName,
                  ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                  ServerSideEncryptionCustomerProvidedKey = base64Key
              };
  
              InitiateMultipartUploadResponse initResponse =
                 await s3Client.InitiateMultipartUploadAsync(initiateRequest);
  
              // 2. Upload Parts.
              long contentLength = new FileInfo(filePath).Length;
              long partSize = 5 * (long)Math.Pow(2, 20); // 5 MB
  
              try
              {
                  long filePosition = 0;
                  for (int i = 1; filePosition < contentLength; i++)
                  {
                      UploadPartRequest uploadRequest = new UploadPartRequest
                      {
                          BucketName = existingBucketName,
                          Key = sourceKeyName,
                          UploadId = initResponse.UploadId,
                          PartNumber = i,
                          PartSize = partSize,
                          FilePosition = filePosition,
                          FilePath = filePath,
                          ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                          ServerSideEncryptionCustomerProvidedKey = base64Key
                      };
  
                      // Upload part and add response to our list.
                      uploadResponses.Add(await s3Client.UploadPartAsync(uploadRequest));
  
                      filePosition += partSize;
                  }
  
                  // Step 3: complete.
                  CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest
                  {
                      BucketName = existingBucketName,
                      Key = sourceKeyName,
                      UploadId = initResponse.UploadId,
                      //PartETags = new List<PartETag>(uploadResponses)
  
                  };
                  completeRequest.AddPartETags(uploadResponses);
  
                  CompleteMultipartUploadResponse completeUploadResponse =
                      await s3Client.CompleteMultipartUploadAsync(completeRequest);
  
              }
              catch (Exception exception)
              {
                  Console.WriteLine("Exception occurred: {0}", exception.Message);
                  AbortMultipartUploadRequest abortMPURequest = new AbortMultipartUploadRequest
                  {
                      BucketName = existingBucketName,
                      Key = sourceKeyName,
                      UploadId = initResponse.UploadId
                  };
                  await s3Client.AbortMultipartUploadAsync(abortMPURequest);
              }
          }
      }
  }
  ```

------

# 封鎖或取消封鎖一般用途儲存貯體的 SSE-C
<a name="blocking-unblocking-s3-c-encryption-gpb"></a>

Amazon S3 中的大多數現代使用案例不再搭配客戶提供的金鑰 (SSE-C) 使用伺服器端加密，因為它缺乏使用 Amazon S3 受管金鑰 (SSE-S3) 的伺服器端加密或 AWS KMS 金鑰 (SSE-KMS) 的伺服器端加密彈性。每次與 SSE-C 加密資料互動時，SSE-C 需要提供加密金鑰，因此與從 S3 儲存貯體讀取資料的其他使用者、角色 AWS 或服務共用 SSE-C 金鑰，以便操作您的資料並不切實際。

若要限制您可以在一般用途儲存貯體中使用的伺服器端加密類型，您可以選擇透過更新儲存貯體的預設加密組態來封鎖 SSE-C 寫入請求。此儲存貯體層級組態會封鎖上傳指定 SSE-C 物件的請求。 當儲存貯體的 SSE-C 遭到封鎖時，任何指定 SSE-C 加密的 `PutObject`、`CopyObject``PostObject`、 或 分段上傳或複寫請求都會遭到 HTTP 403 `AccessDenied`錯誤拒絕。

此設定是 `PutBucketEncryption` API 上的參數，如果您有 `s3:PutEncryptionConfiguration`許可，也可以使用 S3 主控台、 AWS CLI 和 AWS SDKs進行更新。

有效值為 `SSE-C`，可封鎖一般用途儲存貯體的 SSE-C 加密，以及 `NONE`，允許使用 SSE-C 寫入儲存貯體。

**重要**  
如 [2025 年 11 月 19 日所宣布](https://aws.amazon.com/blogs/storage/advanced-notice-amazon-s3-to-disable-the-use-of-sse-c-encryption-by-default-for-all-new-buckets-and-select-existing-buckets-in-april-2026/)，Amazon Simple Storage Service 正在部署新的預設儲存貯體安全設定，以針對所有新的一般用途儲存貯體自動停用使用客戶提供金鑰 (SSE-C) 的伺服器端加密。對於 中沒有 SSE-C 加密物件 AWS 帳戶 的現有儲存貯體，Amazon S3 也會為所有新的寫入請求停用 SSE-C。對於 AWS 帳戶 使用 SSE-C 的 ，Amazon S3 不會變更這些帳戶中任何現有儲存貯體的儲存貯體加密組態。此部署從 2026 年 4 月 6 日開始，並將在接下來的幾週內在 37 AWS 個區域完成，包括 AWS 中國和 AWS GovCloud (US) 區域。  
透過這些變更，需要 SSE-C 加密的應用程式在建立新的儲存貯體之後，必須使用 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) API 操作刻意啟用 SSE-C。如需此變更的詳細資訊，請參閱 [新儲存貯體的預設 SSE-C 設定常見問答集](default-s3-c-encryption-setting-faq.md)。

## 許可
<a name="bucket-encryption-permissions"></a>

使用 `PutBucketEncryption` API 或 S3 主控台、 AWS SDKs或 AWS CLI 來封鎖或取消封鎖一般用途儲存貯體的加密類型。您必須擁有下列許可：
+ `s3:PutEncryptionConfiguration`

使用 `GetBucketEncryption` API 或 S3 主控台、 AWS SDKs或 AWS CLI 來檢視一般用途儲存貯體的封鎖加密類型。您必須擁有下列許可：
+ `s3:GetEncryptionConfiguration`

## 封鎖 SSE-C 加密之前的考量事項
<a name="considerations-before-blocking-sse-c"></a>

封鎖任何儲存貯體的 SSE-C 之後，會套用下列加密行為：
+ 在您封鎖 SSE-C 加密之前，儲存貯體中已存在之物件的加密沒有變更。
+ 封鎖 SSE-C 加密之後，只要您在請求上提供必要的 SSE-C 標頭，您就可以繼續對使用 SSE-C 加密的現有物件提出 GetObject 和 HeadObject 請求。
+ 當儲存貯體的 SSE-C 遭到封鎖時，任何指定 SSE-C `PutObject` `CopyObject`加密的 `PostObject`、、 或 分段上傳請求都會因 HTTP 403 `AccessDenied`錯誤而遭到拒絕。
+ 如果複寫的目的地儲存貯體已封鎖 SSE-C，且複寫的來源物件已使用 SSE-C 加密，複寫將會失敗，並顯示 HTTP 403 `AccessDenied`錯誤。

如果您想要在封鎖此加密類型之前，檢閱您是否在任何儲存貯體中使用 SSE-C 加密，您可以使用 [AWS CloudTrail](https://aws.amazon.com/cloudtrail/) 等工具來監控對資料的存取。此[部落格文章](https://aws.amazon.com/blogs/storage/auditing-amazon-s3-server-side-encryption-methods-for-object-uploads/)說明如何即時稽核物件上傳的加密方法。您也可以參考此 [re：Post 文章](https://repost.aws/articles/ARhGC12rOiTBCKHcAe9GZXCA/how-to-detect-existing-use-of-sse-c-in-your-amazon-s3-buckets)，引導您完成查詢 S3 庫存報告，以查看是否有任何 SSE-C 加密物件。

### 步驟
<a name="block-sse-c-gpb-steps"></a>

您可以使用 Amazon S3 主控台、 AWS Command Line Interface ()、Amazon S3 REST API 和 AWS SDKs，針對一般用途儲存貯體使用客戶提供的金鑰 (SSE-C AWS CLI) 來封鎖或取消封鎖伺服器端加密。

### 使用 S3 主控台
<a name="block-sse-c-gpb-console"></a>

若要使用 Amazon S3 主控台封鎖或取消封鎖儲存貯體的 SSE-C 加密：

1. 登入 AWS 管理主控台，並在 https://console.aws.amazon.com/s3/：// 開啟 Amazon S3 主控台。

1. 在左側導覽窗格中，選擇**一般用途儲存貯**體。

1. 選取您要封鎖 SSE-C 加密的儲存貯體。

1. 選取儲存貯體的**屬性**索引標籤。

1. 導覽至儲存貯體**的預設加密**屬性面板，然後選取**編輯**。

1. 在**封鎖加密類型**區段中，核取**使用客戶提供金鑰 (SSE-C) 的伺服器端加密**旁的方塊，以封鎖 SSE-C 加密，或取消核取此方塊以允許 SSE-C。

1. 選取 **Save Changes** (儲存變更)。

### 使用 AWS CLI
<a name="block-sse-c-gpb-cli"></a>

若要安裝 AWS CLI，請參閱《 [AWS 使用者指南》中的安裝 CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)。 *AWS Command Line Interface *

下列 CLI 範例說明如何使用 來封鎖或取消封鎖一般用途儲存貯體的 SSE-C 加密 AWS CLI。若要使用此命令，請以您自己的資訊取代*使用者輸入預留位置*。

**請求封鎖一般用途儲存貯體的 SSE-C 加密：**

```
aws s3api put-bucket-encryption \
  --bucket amzn-s3-demo-bucket \
  --server-side-encryption-configuration '{
    "Rules": [{
      "BlockEncryptionTypes": {
        "EncryptionType": "SSE-C"
      }
    }]
  }'
```

**請求在一般用途儲存貯體上使用 SSE-C 加密：**

```
aws s3api put-bucket-encryption \
  --bucket amzn-s3-demo-bucket \
  --server-side-encryption-configuration '{
    "Rules": [{
      "BlockEncryptionTypes": {
        "EncryptionType": "NONE"
      }
    }]
  }'
```

## 使用 AWS SDKs
<a name="block-sse-c-gpb-sdks"></a>

------
#### [ SDK for Java 2.x ]

下列範例說明如何使用 AWS SDKs 封鎖或取消封鎖 SSE-C 加密寫入您的一般用途儲存貯體

**範例 - PutBucketEncryption 請求將預設加密組態設定為 SSE-S3 並封鎖 SSE-C**

```
S3Client s3Client = ...;
ServerSideEncryptionByDefault defaultSse = ServerSideEncryptionByDefault
        .builder()
        .sseAlgorithm(ServerSideEncryption.AES256)
        .build();
BlockedEncryptionTypes blockedEncryptionTypes = BlockedEncryptionTypes
        .builder()
        .encryptionType(EncryptionType.SSE_C)
        .build();
ServerSideEncryptionRule rule = ServerSideEncryptionRule.builder()
        .applyServerSideEncryptionByDefault(defaultSse)
        .blockedEncryptionTypes(blockedEncryptionTypes)
        .build();
s3Client.putBucketEncryption(be -> be
        .bucket(bucketName)
        .serverSideEncryptionConfiguration(c -> c.rules(rule)));
```

**範例 - PutBucketEncryption 請求將預設加密組態設定為 SSE-S3 並解除封鎖 SSE-C**

```
S3Client s3Client = ...;
ServerSideEncryptionByDefault defaultSse = ServerSideEncryptionByDefault
        .builder()
        .sseAlgorithm(ServerSideEncryption.AES256)
        .build();
BlockedEncryptionTypes blockedEncryptionTypes = BlockedEncryptionTypes
        .builder()
        .encryptionType(EncryptionType.NONE)
        .build();
ServerSideEncryptionRule rule = ServerSideEncryptionRule.builder()
        .applyServerSideEncryptionByDefault(defaultSse)
        .blockedEncryptionTypes(blockedEncryptionTypes)
        .build();
s3Client.putBucketEncryption(be -> be
        .bucket(bucketName)
        .serverSideEncryptionConfiguration(c -> c.rules(rule)));
```

------
#### [ SDK for Python Boto3 ]

**範例 - PutBucketEncryption 請求將預設加密組態設定為 SSE-S3 並封鎖 SSE-C**

```
s3 = boto3.client("s3")
s3.put_bucket_encryption(
    Bucket="amzn-s3-demo-bucket",
    ServerSideEncryptionConfiguration={
        "Rules":[{
            "ApplyServerSideEncryptionByDefault": {
                "SSEAlgorithm": "AES256"
            },
            "BlockedEncryptionTypes": {
                "EncryptionType": ["SSE-C"]
            }
        }]
    }
)
```

**範例 - PutBucketEncryption 請求將預設加密組態設定為 SSE-S3 並解除封鎖 SSE-C**

```
s3 = boto3.client("s3")
s3.put_bucket_encryption(
    Bucket="amzn-s3-demo-bucket",
    ServerSideEncryptionConfiguration={
        "Rules":[{
            "ApplyServerSideEncryptionByDefault": {
                "SSEAlgorithm": "AES256"
            },
            "BlockedEncryptionTypes": {
                "EncryptionType": ["NONE"]
            }
        }]
    }
)
```

------

## 使用 REST API
<a name="bucket-tag-add-api"></a>

如需有關 Amazon S3 REST API 支援為一般用途儲存貯體破解或取消封鎖 SSE-C 加密的資訊，請參閱《*Amazon Simple Storage Service API 參考*》中的下列章節：
+ 在 [PutBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) 和 GetBucketEncryption API 操作的 ServerSideEncryptionRule 資料類型中使用的 [BlockedEncryptionTypes](https://docs.aws.amazon.com/AmazonS3/latest/API/API_BlockedEncryptionTypes.html) 資料類型。 [ServerSideEncryptionRule](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ServerSideEncryptionRule.html) [GetBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html) 

# 新儲存貯體的預設 SSE-C 設定常見問答集
<a name="default-s3-c-encryption-setting-faq"></a>

**重要**  
如 [2025 年 11 月 19 日所宣布](https://aws.amazon.com/blogs/storage/advanced-notice-amazon-s3-to-disable-the-use-of-sse-c-encryption-by-default-for-all-new-buckets-and-select-existing-buckets-in-april-2026/)，Amazon Simple Storage Service 正在部署新的預設儲存貯體安全設定，以針對所有新的一般用途儲存貯體自動停用使用客戶提供金鑰 (SSE-C) 的伺服器端加密。對於 中沒有 SSE-C 加密物件 AWS 帳戶 的現有儲存貯體，Amazon S3 也會為所有新的寫入請求停用 SSE-C。對於 AWS 帳戶 使用 SSE-C 的 ，Amazon S3 不會變更這些帳戶中任何現有儲存貯體的儲存貯體加密組態。此部署從 2026 年 4 月 6 日開始，並將在接下來的幾週內在 37 AWS 個區域完成，包括 AWS 中國和 AWS GovCloud (US) 區域。  
透過這些變更，需要 SSE-C 加密的應用程式必須在建立新儲存貯體後，使用 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) API 操作刻意啟用 SSE-C。

以下各節回答有關此更新的問題。

**1。在 2026 年 4 月，新的 SSE-C 設定會對所有新建立的儲存貯體生效嗎？**

是。此部署從 2026 年 4 月 6 日開始，並將在接下來的幾週內在 37 AWS 個區域完成，包括 AWS 中國和 AWS GovCloud (US) 區域。

**注意**  
部署完成後，除了中東 （巴林） 和中東 （阿拉伯聯合大公國） 以外的所有 AWS 區域中新建立的儲存貯體預設會停用 SSE-C。

**2. 在此推展涵蓋所有 AWS 區域之前，需要多長時間？**

部署從 2026 年 4 月 6 日開始，將在幾週內完成。

**3. 如何知道更新已完成？**

您可以透過建立新儲存貯體並呼叫 [GetBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html) API 操作來判斷 SSE-C 加密是否已停用，輕鬆判斷變更是否已在您的 AWS 區域中完成。更新完成後，所有新的一般用途儲存貯體都會預設停用 SSE-C 加密。您可以在建立 S3 儲存貯體之後，呼叫 [PutBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) API 操作來調整這些設定。

**4. Amazon S3 是否會更新我現有的儲存貯體組態？**

如果 AWS 您的帳戶沒有任何 SSE-C 加密物件， AWS 會在您所有現有的儲存貯體上停用 SSE-C 加密。如果您 AWS 帳戶中的任何儲存貯體具有 SSE-C 加密物件， AWS 將不會變更該帳戶中任何儲存貯體上的儲存貯體組態。完成您 AWS 區域的`CreateBucket`變更後，新的預設設定將套用至所有新的一般用途儲存貯體。

 **5. 更新完成之前，是否可以停用儲存貯體的 SSE-C 加密？** 

是。您可以呼叫 [PutBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) API 操作並指定新`BlockedEncryptionTypes`標頭，以停用任何儲存貯體的 SSE-C 加密。

**6. 我可以使用 SSE-C 來加密新儲存貯體中的資料嗎？**

是。Amazon S3 中的大多數現代使用案例都不再使用 SSE-C，因為它缺少伺服器端加密的靈活性是使用 Amazon S3 受管金鑰 (SSE-S3) 或使用 AWS KMS 金鑰 (SSE-KMS) 的伺服器端加密。如果您需要在新儲存貯體中使用 SSE-C 加密，您可以建立新的儲存貯體，然後在單獨的`PutBucketEncryption`請求中啟用 SSE-C 加密。

 **範例**

```
aws s3api create-bucket \  
bucket amzn-s3-demo-bucket \ 
region us-east-1 \ 
  
aws s3api put-bucket-encryption \  
-- bucket amzn-s3-demo-bucket \
-- server-side-encryption-configuration \
'{ \Rules\: [{   
   {   
   \ApplyServerSideEncryptionByDefault\: {   
     \SSEAlgorithm\: \AES256\,  
    },   
   \BlockedEncryptionTypes\: [  
     \EncryptionType\:\NONE\]   
   }   
   }]   
}'
```

**注意**  
您必須擁有呼叫 `PutBucketEncryption` API 的`s3:PutEncryptionConfiguration`許可。

**7. 封鎖 SSE-C 如何影響對儲存貯體的請求？**

當儲存貯體的 SSE-C 遭到封鎖時，任何指定 SSE-C 加密的 `PutObject`、`CopyObject``PostObject`、 或 分段上傳或複寫請求都會遭到 HTTP 403 `AccessDenied`錯誤拒絕。