

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

# 第 3 版中的 Amazon S3 用戶端加密 適用於 PHP 的 AWS SDK
<a name="s3-encryption-client"></a>

使用用戶端加密時，會直接在您的環境中將資料加密和解密。這表示此資料在傳輸至 Amazon S3 之前會先加密，而且您不需要依賴外部服務來為您處理加密。對於新的實作，我們建議在 `S3EncryptionClientV3`和 `S3EncryptionMultipartUploaderV3` 以及已棄用 `S3EncryptionClientV2``S3EncryptionMultipartUploaderV2`和 上使用 `S3EncryptionClient`和 `S3EncryptionMultipartUploader`。建議仍然使用已棄用版本的舊實作嘗試遷移。 會`S3EncryptionClientV3`維持對使用舊版 加密資料的解密支援`S3EncryptionClient`。

 適用於 PHP 的 AWS SDK 實作[信封加密](https://docs.aws.amazon.com/kms/latest/developerguide/workflow.html)，並使用 [OpenSSL](https://www.openssl.org/) 進行加密和解密。這項實作功能可與[符合其功能支援的其他開發套件](https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html)互通，也相容於[軟體開發套件採用 promise 的非同步工作流程](guide_promises.md)。

## 遷移指南
<a name="migration-guide"></a>

對於嘗試從已棄用用戶端遷移到新用戶端的人員，這裡有從 v1 遷移到 v2 的遷移指南，[https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/s3-encryption-migration-v1-v2-section.html](https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/s3-encryption-migration-v1-v2-section.html)以及從 v2 遷移到 v3 [的](https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/s3-encryption-migration-v2-v3-section.html)遷移指南。

## 設定
<a name="setup"></a>

若要開始使用用戶端加密，您需要下列項目：
+ [AWS KMS 加密金鑰](https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html) 
+ [S3 儲存貯體](https://docs.aws.amazon.com/AmazonS3/latest/gsg/CreatingABucket.html) 

在執行任何範例程式碼之前，請先設定您的 AWS 登入資料。請參閱第 [3 適用於 PHP 的 AWS SDK 版的登入](guide_credentials.md)資料。

## 加密
<a name="encryption"></a>

在 中上傳加密的物件`S3EncryptionClientV3`，除了標準參數之外，還需要四個額外的`PutObject`參數：
+  `'@KmsEncryptionContext'` 是金鑰/值對，可用於為您的加密物件新增額外的安全層。加密用戶端必須傳入相同的金鑰，該金鑰會在取得呼叫時自動執行。如果不需要其他內容，請傳入空白陣列。
+  `@CipherOptions` 是加密的其他組態，包括要使用的加密和 keysize。
+  `@MaterialsProvider` 是處理產生加密金鑰和初始化向量，以及加密加密金鑰的提供者。
+  `@CommitmentPolicy` 是政策選項，指示如何使用金鑰承諾或不使用金鑰承諾來讀取物件，以及如何使用金鑰承諾或不使用金鑰承諾來寫入物件。

```
use Aws\S3\S3Client;
use Aws\S3\Crypto\S3EncryptionClientV3;
use Aws\Kms\KmsClient;
use Aws\Crypto\KmsMaterialsProviderV3;

 // Let's construct our S3EncryptionClient using an S3Client
 $encryptionClient = new S3EncryptionClientV3(
     new S3Client([
         'profile' => 'default',
         'region' => 'us-east-1',
         'version' => 'latest',
     ])
 );

 $kmsKeyId = 'kms-key-id';
 $materialsProvider = new KmsMaterialsProviderV3(
     new KmsClient([
         'profile' => 'default',
         'region' => 'us-east-1',
         'version' => 'latest',
     ]),
     $kmsKeyId
 );

 $bucket = 'the-bucket-name';
 $key = 'the-file-name';
 $cipherOptions = [
     'Cipher' => 'gcm',
     'KeySize' => 256,
     // Additional configuration options
 ];

 $result = $encryptionClient->putObject([
     '@MaterialsProvider' => $materialsProvider,
     '@CipherOptions' => $cipherOptions,
     '@CommitmentPolicy' => 'REQUIRE_ENCRYPT_REQUIRE_DECRYPT',
     '@KmsEncryptionContext' => ['context-key' => 'context-value'],
     'Bucket' => $bucket,
     'Key' => $key,
     'Body' => fopen('file-to-encrypt.txt', 'r'),
 ]);
```

**注意**  
除了 Amazon S3 和 AWS KMS型服務錯誤之外，如果`'@CipherOptions'`未正確設定 ，您可能會收到擲出的`InvalidArgumentException`物件。

## 解密
<a name="decryption"></a>

除了標準參數之外，下載和解密物件還有五個額外的`GetObject`參數，其中兩個是必要的。用戶端會為您偵測基本密碼選項。
+   
** `'@SecurityProfile'`：如果設定為「V3」，則只有與 V3-compatible加密的物件**  
格式可以解密。將此參數設為「V3\$1AND\$1LEGACY」也允許解密以 V1-compatible格式加密的物件。若要支援遷移，請將 @SecurityProfile 設定為「V3\$1AND\$1LEGACY」。僅使用「V3」進行新的應用程式開發。
+   
** `'@MaterialsProvider'` 是處理產生加密金鑰和初始化向量的供應商，**  
以及加密您的密碼金鑰。
+   
** `'@KmsAllowDecryptWithAnyCmk'`：（選用） 將此參數設為 true 可啟用解密**  
但不提供 KMS 金鑰 ID 給 MaterialsProvider 的建構函式。預設值為 false。
+   
** `'@CipherOptions'` （選用） 是加密的其他組態，包括**  
要使用的 密碼和 keysize。
+   
** `@CommitmentPolicy` 政策選項，指示如何使用 讀取物件 **  
金鑰承諾或沒有金鑰承諾，以及如何使用金鑰承諾或沒有金鑰承諾來寫入物件。

```
$result = $encryptionClient->getObject([
    '@KmsAllowDecryptWithAnyCmk' => true,
    '@SecurityProfile' => 'V2_AND_LEGACY',
    '@CommitmentPolicy' => 'REQUIRE_ENCRYPT_ALLOW_DECRYPT',
    '@MaterialsProvider' => $materialsProvider,
    '@CipherOptions' => $cipherOptions,
    'Bucket' => $bucket,
    'Key' => $key,
]);
```

**注意**  
除了 Amazon S3 和 AWS KMS型服務錯誤之外，如果`'@CipherOptions'`未正確設定 ，您可能會收到擲出的`InvalidArgumentException`物件。

## 密碼組態
<a name="cipher-configuration"></a>

** `'Cipher'` (string)**  
加密用戶端在加密時所使用的加密方法。目前僅支援「gcm」。

**重要**  
PHP 的 [7.1 版已更新](http://php.net/manual/en/migration71.new-features.php)，納入了額外的必要參數，以使用 OpenSSL 進行 GCM 加密的[加密](http://php.net/manual/en/function.openssl-encrypt.php)和[解密](http://php.net/manual/en/function.openssl-decrypt.php)動作。對於 PHP 7.0 版和更早版本，加密用戶端和 會提供`S3EncryptionClientV2`並使用 GCM 支援的 polyfill`S3EncryptionMultipartUploaderV2`。不過，與使用 PHP 7.1\$1 的原生實作相比，使用 polyfill 對大型輸入的效能會慢得多，因此可能需要升級較舊的 PHP 版本環境，才能有效地使用這些環境。

** `'KeySize'` (int)**  
進行加密所需產生的內容加密金鑰的長度。預設值為 256 位元。有效的組態選項為 256 位元。

** `'Aad'` (string)**  
要選用地包含在您加密承載中的「其他身分驗證資料」。解密時會驗證這項資訊。`Aad` 僅在使用「gcm」加密法時才能使用。

**重要**  
 AWS SDKs 不支援其他身分驗證資料，因此其他SDKs可能無法解密使用此參數加密的檔案。

## 中繼資料策略
<a name="metadata-strategies"></a>

您也可以選擇針對實作 `Aws\Crypto\MetadataStrategyInterface` 的類別，來提供其執行個體。這個簡單的界面可儲存和載入 `Aws\Crypto\MetadataEnvelope`，其中包含您的信封加密資料。開發套件提供了實作此項目的兩個類別：`Aws\S3\Crypto\HeadersMetadataStrategy` 與 `Aws\S3\Crypto\InstructionFileMetadataStrategy`。預設會使用 `HeadersMetadataStrategy`。

```
$strategy = new InstructionFileMetadataStrategy(
    $s3Client
);

$encryptionClient->putObject([
    '@MaterialsProvider' => $materialsProvider,
    '@MetadataStrategy' => $strategy,
    '@CommitmentPolicy' => 'REQUIRE_ENCRYPT_REQUIRE_DECRYPT',
    '@KmsEncryptionContext' => [],
    '@CipherOptions' => $cipherOptions,
    'Bucket' => $bucket,
    'Key' => $key,
    'Body' => fopen('file-to-encrypt.txt', 'r'),
]);

$result = $encryptionClient->getObject([
    '@KmsAllowDecryptWithAnyCmk' => false,
    '@MaterialsProvider' => $materialsProvider,
    '@SecurityProfile' => 'V3',
    '@CommitmentPolicy' => 'REQUIRE_ENCRYPT_REQUIRE_DECRYPT',
    '@MetadataStrategy' => $strategy,
    '@CipherOptions' => $cipherOptions,
    'Bucket' => $bucket,
    'Key' => $key,
]);
```

您也可透過呼叫 `HeadersMetadataStrategy`::class`InstructionFileMetadataStrategy`，來提供 * 和 * 的類別名稱常數。

```
$result = $encryptionClient->putObject([
    '@MaterialsProvider' => $materialsProvider,
    '@CommitmentPolicy' => 'REQUIRE_ENCRYPT_REQUIRE_DECRYPT',
    '@MetadataStrategy' => HeadersMetadataStrategy::class,
    '@CipherOptions' => $cipherOptions,
    'Bucket' => $bucket,
    'Key' => $key,
    'Body' => fopen('file-to-encrypt.txt', 'r'),
]);
```

**注意**  
如果在上傳指令檔案後發生故障，不會自動刪除該檔案。

## 分段上傳
<a name="multipart-uploads"></a>

您也可以使用用戶端加密來進行分段上傳。會在上傳之前`Aws\S3\Crypto\S3EncryptionMultipartUploaderV3`準備來源串流以進行加密。建立的方法類似於使用 `Aws\S3\MultipartUploader` 和 `Aws\S3\Crypto\S3EncryptionClientV3` 時的經驗。`S3EncryptionMultipartUploaderV3` 可以處理與 `'@MetadataStrategy'` 相同的 `S3EncryptionClientV3` 選項，以及所有可用的 `'@CipherOptions'` 組態。

```
$kmsKeyId = 'kms-key-id';
$materialsProvider = new KmsMaterialsProviderV3(
    new KmsClient([
        'region' => 'us-east-1',
        'version' => 'latest',
        'profile' => 'default',
    ]),
    $kmsKeyId
);

$bucket = 'the-bucket-name';
$key = 'the-upload-key';
$cipherOptions = [
    'Cipher' => 'gcm'
    'KeySize' => 256,
    // Additional configuration options
];

$multipartUploader = new S3EncryptionMultipartUploaderV3(
    new S3Client([
        'region' => 'us-east-1',
        'version' => 'latest',
        'profile' => 'default',
    ]),
    fopen('large-file-to-encrypt.txt', 'r'),
    [
        '@MaterialsProvider' => $materialsProvider,
        '@CipherOptions' => $cipherOptions,
        '@CommitmentPolicy' => 'REQUIRE_ENCRYPT_REQUIRE_DECRYPT',
        'bucket' => $bucket,
        'key' => $key,
    ]
);
$multipartUploader->upload();
```

**注意**  
除了 Amazon S3 和 AWS KMS型服務錯誤之外，如果`'@CipherOptions'`未正確設定 ，您可能會收到擲出的`InvalidArgumentException`物件。