

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

# AWS 加密 CLI 的範例
<a name="crypto-cli-examples"></a>

使用以下範例，在您偏好的平台上嘗試 AWS 加密 CLI。如需主金鑰和其他參數的說明，請參閱[如何使用 AWS 加密 CLI](crypto-cli-how-to.md)。如需快速參考，請參閱 [AWS Encryption SDK CLI 語法和參數參考](crypto-cli-reference.md)。

**注意**  
下列範例使用 AWS 加密 CLI 2.1.*x* 版的語法。  
新的安全功能最初在 AWS 加密 CLI 版本 1.7.*x* 和 2.0.*x* 中發行。不過， AWS Encryption CLI 1.8.*x* 版取代了 1.7.*x* 版，而 AWS Encryption CLI 2.1.*x* 版取代了 2.0.*x*。如需詳細資訊，請參閱 GitHub 上 [aws-encryption-sdk-cli](https://github.com/aws/aws-encryption-sdk-cli/) 儲存庫的相關[安全建議](https://github.com/aws/aws-encryption-sdk-cli/security/advisories/GHSA-2xwp-m7mq-7q3r)。

如需示範如何使用限制加密資料金鑰之安全功能的範例，請參閱 [限制加密的資料金鑰](configure.md#config-limit-keys)。

如需示範如何使用 AWS KMS 多區域金鑰的範例，請參閱 [使用多區域 AWS KMS keys](configure.md#config-mrks)。

**Topics**
+ [加密檔案](#cli-example-encrypt-file)
+ [解密檔案](#cli-example-decrypt-file)
+ [加密目錄中的所有檔案](#cli-example-encrypt-directory)
+ [解密目錄中的所有檔案](#cli-example-decrypt-directory)
+ [在命令列上加密和解密](#cli-example-stdin)
+ [使用多個主金鑰](#cli-example-multimaster)
+ [在指令碼中加密和解密](#cli-example-script)
+ [使用資料金鑰快取](#cli-example-caching)

## 加密檔案
<a name="cli-example-encrypt-file"></a>

此範例使用 AWS 加密 CLI 來加密 `hello.txt` 檔案的內容，其中包含「Hello World」字串。

當您在檔案上執行加密命令時， AWS 加密 CLI 會取得檔案的內容、產生唯一的[資料金鑰](concepts.md#DEK)、在資料金鑰下加密檔案內容，然後將[加密的訊息](concepts.md#message)寫入新檔案。

第一個命令會將 的金鑰 ARN 儲存在 `$keyArn`變數 AWS KMS key 中。使用 加密時 AWS KMS key，您可以使用金鑰 ID、金鑰 ARN、別名名稱或別名 ARN 來識別它。如需 金鑰識別符的詳細資訊 AWS KMS key，請參閱《 *AWS Key Management Service 開發人員指南*》中的[金鑰識別符](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id)。

第二個命令會加密檔案內容。此命令會使用 `--encrypt` 參數來指定操作和 `--input` 參數，以指示需要加密的檔案。[`--wrapping-keys` 參數](crypto-cli-how-to.md#crypto-cli-master-key)及其所需的**金鑰**屬性，指示 命令使用由金鑰 ARN AWS KMS key 表示的 。

此命令會使用 `--metadata-output` 參數，指定用於加密操作相關中繼資料的文字檔案。根據最佳實務，此命令會使用 `--encryption-context` 參數來指定[加密細節](crypto-cli-how-to.md#crypto-cli-encryption-context)。

此命令也會使用 [`--commitment-policy` 參數](crypto-cli-reference.md#syntax-commitment-policy)來明確設定承諾政策。在 1.8.*x* 版中，當您使用 參數時，需要此`--wrapping-keys`參數。從 2.1.*x* 版開始， `--commitment-policy` 參數是選用的，但建議使用。

`--output` 參數的值，也就是點 (.)，則會通知此命令要將輸出檔寫入目前的目錄。

------
#### [ Bash ]

```
\\ To run this example, replace the fictitious key ARN with a valid value.
$ keyArn=arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab

$ aws-encryption-cli --encrypt \
                     --input hello.txt \
                     --wrapping-keys key=$keyArn \
                     --metadata-output ~/metadata \
                     --encryption-context purpose=test \
                     --commitment-policy require-encrypt-require-decrypt \
                     --output .
```

------
#### [ PowerShell ]

```
# To run this example, replace the fictitious key ARN with a valid value.
PS C:\> $keyArn = 'arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'

PS C:\> aws-encryption-cli --encrypt `
                           --input Hello.txt `
                           --wrapping-keys key=$keyArn `
                           --metadata-output $home\Metadata.txt `
                           --commitment-policy require-encrypt-require-decrypt `
                           --encryption-context purpose=test `
                           --output .
```

------

當執行成功時，加密命令並不會傳回任何輸出。若要判斷命令是否執行成功，請查看 `$?` 變數的布林值。當命令執行成功時，`$?` 的值會是 `0` (Bash) 或 `True` (PowerShell)。當命令執行失敗時，`$?` 的值會是非零 (Bash) 或 `False` (PowerShell)。

------
#### [ Bash ]

```
$ echo $?
0
```

------
#### [ PowerShell ]

```
PS C:\> $?
True
```

------

您也可以使用目錄列出命令，查看加密命令是否建立了新的檔案 `hello.txt.encrypted`。由於加密命令未指定輸出的檔案名稱，因此 AWS Encryption CLI 會將輸出寫入與輸入檔案同名的檔案，加上`.encrypted`尾碼。若要使用不同的尾碼或隱藏尾碼，請使用 `--suffix` 參數。

`hello.txt.encrypted` 檔案包含了[加密的訊息](concepts.md#message)，當中包含 `hello.txt` 檔案的加密文字、資料金鑰的加密副本，以及包括加密細節的額外中繼資料。

------
#### [ Bash ]

```
$  ls
hello.txt  hello.txt.encrypted
```

------
#### [ PowerShell ]

```
PS C:\> dir

    Directory: C:\TestCLI

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        9/15/2017   5:57 PM             11 Hello.txt
-a----        9/17/2017   1:06 PM            585 Hello.txt.encrypted
```

------

## 解密檔案
<a name="cli-example-decrypt-file"></a>

此範例使用 AWS 加密 CLI 來解密先前範例中加密`Hello.txt.encrypted`的檔案內容。

此解密命令會使用 `--decrypt` 參數來指示操作和 `--input` 參數，以確認需要解密的檔案。`--output` 參數的值是一個點，即代表目前的目錄。

具有**金鑰**屬性的 `--wrapping-keys` 參數會指定用於解密加密訊息的包裝金鑰。在使用 解密命令中 AWS KMS keys，金鑰屬性的值必須是[金鑰 ARN](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN)。解密命令中需要 `--wrapping-keys` 參數。如果您使用的是 AWS KMS keys，您可以使用**金鑰**屬性來指定 AWS KMS keys 進行解密，或使用值為 `true`（但不能同時指定兩者） 的**探索**屬性。如果您使用的是自訂主金鑰提供者，則需要**金鑰**和**提供者**屬性。

從 2.1.*x* 版開始， [`--commitment-policy` 參數](crypto-cli-reference.md#syntax-commitment-policy)是選用的，但建議使用。使用它可以明確地讓您的意圖清晰，即使您指定了預設值 `require-encrypt-require-decrypt`。

`--encryption-context` 參數在解密命令中屬於選用性，即使加密命令中已有提供[加密細節](crypto-cli-how-to.md#crypto-cli-encryption-context)。遇到這種情況時，解密命令會使用加密命令所提供的相同加密細節。在解密之前， AWS 加密 CLI 會驗證加密訊息中的加密內容是否包含`purpose=test`配對。如果沒有包含，解密命令執行就會失敗。

`--metadata-output` 參數會指定用於解密操作相關中繼資料的檔案。`--output` 參數的值，也就是點 (.)，則會將輸出檔寫入目前的目錄。

最佳實務是使用 `--max-encrypted-data-keys` 參數，以避免解密格式不正確的訊息，其中包含過多的加密資料金鑰。指定預期的加密資料金鑰數量 （用於加密的每個包裝金鑰各一個） 或合理的上限 （例如 5)。如需詳細資訊，請參閱[限制加密的資料金鑰](configure.md#config-limit-keys)。

只有在處理所有輸入之後， 才會`--buffer`傳回純文字，包括驗證存在的數位簽章。

------
#### [ Bash ]

```
\\ To run this example, replace the fictitious key ARN with a valid value.
$ keyArn=arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab

$ aws-encryption-cli --decrypt \
                     --input hello.txt.encrypted \
                     --wrapping-keys key=$keyArn \
                     --commitment-policy require-encrypt-require-decrypt \
                     --encryption-context purpose=test \
                     --metadata-output ~/metadata \
                     --max-encrypted-data-keys 1 \
                     --buffer \
                     --output .
```

------
#### [ PowerShell ]

```
\\ To run this example, replace the fictitious key ARN with a valid value.
PS C:\> $keyArn = 'arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'

PS C:\> aws-encryption-cli --decrypt `
                           --input Hello.txt.encrypted `
                           --wrapping-keys key=$keyArn `
                           --commitment-policy require-encrypt-require-decrypt `
                           --encryption-context purpose=test `
                           --metadata-output $home\Metadata.txt `
                           --max-encrypted-data-keys 1 `
                           --buffer `
                           --output .
```

------

當執行成功時，解密命令並不會傳回任何輸出。若要判斷命令是否執行成功，請取得 `$?` 變數的值。您也可以使用目錄列出命令，查看此命令是否建立了另加尾碼 `.decrypted` 的新檔案。若要查看純文字內容，請使用命令以取得該檔案內容，例如 `cat` 或 [Get-Content](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-content)。

------
#### [ Bash ]

```
$  ls
hello.txt  hello.txt.encrypted  hello.txt.encrypted.decrypted

$  cat hello.txt.encrypted.decrypted
Hello World
```

------
#### [ PowerShell ]

```
PS C:\> dir

    Directory: C:\TestCLI

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        9/17/2017   1:01 PM             11 Hello.txt
-a----        9/17/2017   1:06 PM            585 Hello.txt.encrypted
-a----        9/17/2017   1:08 PM             11 Hello.txt.encrypted.decrypted


PS C:\> Get-Content Hello.txt.encrypted.decrypted
Hello World
```

------

## 加密目錄中的所有檔案
<a name="cli-example-encrypt-directory"></a>

此範例使用 AWS 加密 CLI 來加密目錄中所有檔案的內容。

當命令影響多個檔案時， AWS 加密 CLI 會個別處理每個檔案。它會取得檔案內容、從主金鑰取得該檔案的唯一[資料金鑰](concepts.md#DEK)、根據該資料金鑰來加密檔案內容，接著將結果寫入在輸出目錄中的新檔案。因此，您可以獨立解密處理輸出檔。

這份 `TestDir` 目錄清單顯示了我們要加密的純文字檔案。

------
#### [ Bash ]

```
$  ls testdir
cool-new-thing.py  hello.txt  employees.csv
```

------
#### [ PowerShell ]

```
PS C:\> dir C:\TestDir

    Directory: C:\TestDir

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        9/12/2017   3:11 PM           2139 cool-new-thing.py
-a----        9/15/2017   5:57 PM             11 Hello.txt
-a----        9/17/2017   1:44 PM             46 Employees.csv
```

------

第一個命令會將 的 [Amazon Resource Name (ARN)](https://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html#find-cmk-id-arn) 儲存在 `$keyArn`變數 AWS KMS key 中。

第二個命令會加密在 `TestDir` 目錄中之檔案的內容，並將加密細節的檔案寫入 `TestEnc` 目錄。如果該 `TestEnc` 目錄不存在，命令執行就會失敗。由於輸入位置是一個目錄，所以必須使用 `--recursive` 參數。

[`--wrapping-keys` 參數](crypto-cli-how-to.md#crypto-cli-master-key)及其所需的**金鑰**屬性，指定要使用的包裝金鑰。此加密命令會包含[加密細節](crypto-cli-how-to.md#crypto-cli-encryption-context)、`dept=IT`。當您在執行加密多個檔案的加密命令中指定某加密細節時，所有檔案都會使用該相同加密細節。

命令也有 `--metadata-output` 參數，可告知 AWS 加密 CLI 在何處寫入有關加密操作的中繼資料。Encryption AWS CLI 會為每個加密的檔案寫入一個中繼資料記錄。

從 2.1.*x* 版開始， [`--commitment-policy parameter`](crypto-cli-how-to.md#crypto-cli-commitment-policy)是選用的，但建議使用。如果命令或指令碼因為無法解密加密文字而失敗，明確承諾政策設定可協助您快速偵測問題。

當命令完成時， AWS 加密 CLI 會將加密的檔案寫入`TestEnc`目錄，但不會傳回任何輸出。

最後的命令會列出 `TestEnc` 目錄中的檔案。每個純文字內容的輸入檔案，都會有一個加密細節的輸出檔案。由於此命令沒有指定替代尾碼，所以加密命令會在每個輸入檔名後面加上 `.encrypted`。

------
#### [ Bash ]

```
# To run this example, replace the fictitious key ARN with a valid master key identifier.
$  keyArn=arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab

$ aws-encryption-cli --encrypt \
                     --input testdir --recursive\
                     --wrapping-keys key=$keyArn \
                     --encryption-context dept=IT \
                     --commitment-policy require-encrypt-require-decrypt \
                     --metadata-output ~/metadata \
                     --output testenc

$ ls testenc
cool-new-thing.py.encrypted  employees.csv.encrypted  hello.txt.encrypted
```

------
#### [ PowerShell ]

```
# To run this example, replace the fictitious key ARN with a valid master key identifier.
PS C:\> $keyArn = arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab

PS C:\> aws-encryption-cli --encrypt `
                           --input .\TestDir --recursive `
                           --wrapping-keys key=$keyArn `
                           --encryption-context dept=IT `
                           --commitment-policy require-encrypt-require-decrypt `
                           --metadata-output .\Metadata\Metadata.txt `
                           --output .\TestEnc

PS C:\> dir .\TestEnc

    Directory: C:\TestEnc

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        9/17/2017   2:32 PM           2713 cool-new-thing.py.encrypted
-a----        9/17/2017   2:32 PM            620 Hello.txt.encrypted
-a----        9/17/2017   2:32 PM            585 Employees.csv.encrypted
```

------

## 解密目錄中的所有檔案
<a name="cli-example-decrypt-directory"></a>

這個範例會解密目錄中的所有檔案。範例一開始是先處理位在 `TestEnc` 目錄中，先前範例所加密的檔案。

------
#### [ Bash ]

```
$  ls testenc
cool-new-thing.py.encrypted  hello.txt.encrypted  employees.csv.encrypted
```

------
#### [ PowerShell ]

```
PS C:\> dir C:\TestEnc

    Directory: C:\TestEnc

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        9/17/2017   2:32 PM           2713 cool-new-thing.py.encrypted
-a----        9/17/2017   2:32 PM            620 Hello.txt.encrypted
-a----        9/17/2017   2:32 PM            585 Employees.csv.encrypted
```

------

這個解密命令會解密在 TestEnc 目錄中的所有檔案，接著將純文字檔案寫入 TestDec 目錄。具有**金鑰**屬性和[金鑰 ARN](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN) 值的 `--wrapping-keys` 參數會告知 AWS 加密 CLI AWS KMS keys 要使用哪個項目來解密檔案。命令使用 `--interactive` 參數來指示 AWS 加密 CLI 在覆寫具有相同名稱的檔案之前提示您。

此命令也會使用在先前加密檔案時所提供的加密細節。解密多個檔案時， AWS 加密 CLI 會檢查每個檔案的加密內容。如果任何檔案的加密內容檢查失敗， AWS 加密 CLI 會拒絕檔案、寫入警告、在中繼資料中記錄失敗，然後繼續檢查剩餘的檔案。如果 AWS 加密 CLI 因任何其他原因而無法解密檔案，整個解密命令會立即失敗。

在這個範例中，所有輸入檔中的已加密訊息都會包含 `dept=IT` 加密細節元素。不過，如果要解密的訊息採用不同的加密細節，這時您應該還是可以驗證部分的加密細節。例如，如果某些訊息包含 `dept=finance` 的加密細節，而其他訊息包含的是 `dept=IT`，這時您不用指定該值，就能驗證加密細節是否一直包含 `dept` 名稱。如果您想要設定更多限定，您可以使用個別命令來解密這些檔案。

解密命令不會傳回任何輸出，但您可以使用目錄列出命令，查看其是否建立了另加 `.decrypted` 尾碼的新檔案。若要查看純文字內容，請使用命令以取得該檔案內容。

------
#### [ Bash ]

```
# To run this example, replace the fictitious key ARN with a valid master key identifier.
$ keyArn=arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab

$ aws-encryption-cli --decrypt \
                     --input testenc --recursive \
                     --wrapping-keys key=$keyArn \
                     --encryption-context dept=IT \
                     --commitment-policy require-encrypt-require-decrypt \
                     --metadata-output ~/metadata \
                     --max-encrypted-data-keys 1 \
                     --buffer \
                     --output testdec --interactive

$ ls testdec
cool-new-thing.py.encrypted.decrypted  hello.txt.encrypted.decrypted  employees.csv.encrypted.decrypted
```

------
#### [ PowerShell ]

```
# To run this example, replace the fictitious key ARN with a valid master key identifier.
PS C:\> $keyArn = 'arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'

PS C:\> aws-encryption-cli --decrypt `
                           --input C:\TestEnc --recursive `
                           --wrapping-keys key=$keyArn `
                           --encryption-context dept=IT `
                           --commitment-policy require-encrypt-require-decrypt `
                           --metadata-output $home\Metadata.txt `
                           --max-encrypted-data-keys 1 `
                           --buffer `
                           --output C:\TestDec --interactive

PS C:\> dir .\TestDec


    Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        10/8/2017   4:57 PM           2139 cool-new-thing.py.encrypted.decrypted
-a----        10/8/2017   4:57 PM             46 Employees.csv.encrypted.decrypted
-a----        10/8/2017   4:57 PM             11 Hello.txt.encrypted.decrypted
```

------

## 在命令列上加密和解密
<a name="cli-example-stdin"></a>

這些範例會示範如何將輸入輸送到命令 (stdin)，以及將輸出寫入命令列 (stdout)。範例會說明如何在命令中表示 stdin、stdout，以及如何使用內建的 Base64 編碼工具防止 shell 錯誤解譯非 ASCII 字元。

這個範例會將純文字字串輸送到加密命令，並將加密的訊息儲存到變數中。然後，它會將變數中的已加密訊息輸送到解密命令，再由該命令將其輸出寫入到管道 (stdout)。

範例中包含了三種命令：
+ 第一個命令會將 的[金鑰 ARN](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN) 儲存在 `$keyArn`變數 AWS KMS key 中。

------
#### [ Bash ]

  ```
  $  keyArn=arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
  ```

------
#### [ PowerShell ]

  ```
  PS C:\> $keyArn = 'arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'
  ```

------

   
+ 第二個命令會將 `Hello World` 字串輸送到加密命令，並將執行結果儲存到 `$encrypted` 變數中。

  所有 AWS Encryption CLI 命令都需要 `--input`和 `--output` 參數。若要指示輸入要輸送到命令 (stdin)，`-` 參數的值應使用連字號 (`--input`)。若要將輸出傳送到命令列 (stdout)，`--output` 參數的值應使用連字號。

  `--encode` 參數會先對輸出進行 Base64 編碼，再將其傳回。這樣可以防止 shell 錯誤解譯已加密訊息中的非 ASCII 字元。

  由於這個命令只是為了概念驗證，所以我們會省略加密細節，並且隱藏中繼資料 (`-S`)。

------
#### [ Bash ]

  ```
  $ encrypted=$(echo 'Hello World' | aws-encryption-cli --encrypt -S \
                                                        --input - --output - --encode \
                                                        --wrapping-keys key=$keyArn )
  ```

------
#### [ PowerShell ]

  ```
  PS C:\> $encrypted = 'Hello World' | aws-encryption-cli --encrypt -S `
                                                          --input - --output - --encode `
                                                          --wrapping-keys key=$keyArn
  ```

------

   
+ 第三個命令會將 `$encrypted` 變數中的已加密訊息輸送到解密命令。

  這個解密命令會使用 `--input -`，指示輸入會由該管道送入 (stdin)，而且使用 `--output -` 將輸出傳送到該管道 (stdout)。(輸入參數接收的是輸入的位置，而非實際的輸入位元組，因此您不能使用 `$encrypted` 變數做為 `--input` 參數值)。

  此範例使用 `--wrapping-keys` 參數的 **探索**屬性，以允許 AWS 加密 CLI 使用任何 AWS KMS key 來解密資料。它不會指定[承諾政策](concepts.md#commitment-policy)，因此會使用 2.1.*x* 版和更新版本的預設值 `require-encrypt-require-decrypt`。

  由於輸出是經過加密後再進行編碼，所以解密命令會先使用 `--decode` 參數來解碼經 Base64 編碼處理的輸入，接著再進行解密。您也可以先使用 `--decode` 參數，為經 Base64 編碼處理的解碼，接著再進行加密。

  同樣地，這個命令會省略加密細節，並隱藏中繼資料 (-`S`)。

------
#### [ Bash ]

  ```
  $  echo $encrypted | aws-encryption-cli --decrypt --wrapping-keys discovery=true --input - --output - --decode --buffer -S
  Hello World
  ```

------
#### [ PowerShell ]

  ```
  PS C:\> $encrypted | aws-encryption-cli --decrypt --wrapping-keys discovery=$true --input - --output - --decode --buffer -S
  Hello World
  ```

------

您也可以運用單一個命令來執行加密和解密操作，完全不用中斷變數。

在上述範例中，`--input` 和 `--output` 參數具有 `-` 值，而此命令會使用 `--encode` 參數來為輸出進行編碼，並使用 `--decode` 參數來為輸入進行解碼。

------
#### [ Bash ]

```
$  keyArn=arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab

$  echo 'Hello World' |
          aws-encryption-cli --encrypt --wrapping-keys key=$keyArn --input - --output - --encode -S |
          aws-encryption-cli --decrypt --wrapping-keys discovery=true --input - --output - --decode -S
Hello World
```

------
#### [ PowerShell ]

```
PS C:\> $keyArn = 'arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'

PS C:\> 'Hello World' |
               aws-encryption-cli --encrypt --wrapping-keys key=$keyArn --input - --output - --encode -S |
               aws-encryption-cli --decrypt --wrapping-keys discovery=$true --input - --output - --decode -S
Hello World
```

------

## 使用多個主金鑰
<a name="cli-example-multimaster"></a>

此範例示範如何在加密 AWS CLI 中加密和解密資料時使用多個主金鑰。

如果您是使用多個主金鑰來加密資料，則其中任何一個主金鑰都可用來為資料進行解密。這個策略可確保您一定可以解密資料，即使其中一個主金鑰發生不可用的情況。如果您要將加密的資料儲存在多個 中 AWS 區域，此策略可讓您在相同區域中使用主金鑰來解密資料。

當您使用多個主金鑰來進行加密時，第一個主金鑰會扮演特殊的角色。它會產生將在資料加密時所用到的資料金鑰。其餘的主金鑰則加密處理純文字的資料金鑰。結果產生的[加密的訊息](concepts.md#message)，包含了該已加密資料和已加密資料金鑰的集合，每則訊息會對應到個別主金鑰。雖然第一個主金鑰會產生資料金鑰，但其中任何一個主金鑰都可以解密處理任何一個可用來解密處理資料的資料金鑰。

**使用三個主金鑰加密**

此範例命令使用三個包裝金鑰來加密`Finance.log`檔案，每個檔案各一個 AWS 區域。

它會將加密的訊息寫入到 `Archive` 目錄。此命令會使用 `--suffix` 參數，且不指定隱藏尾碼的參數值，因此輸入和輸出檔的名稱都是相同的。

此命令會使用 `--wrapping-keys` 參數，並指定三個 **key** 屬性。您也可以在相同的命令中使用多個 `--wrapping-keys` 參數。

若要加密日誌檔案， AWS Encryption CLI 會要求清單中的第一個包裝金鑰 `$key1`產生用來加密資料的資料金鑰。然後，它會使用其他每個包裝金鑰來加密相同資料金鑰的純文字副本。在輸出檔案中的已加密訊息，包含了全部三個的已加密資料金鑰。

------
#### [ Bash ]

```
$ key1=arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
$ key2=arn:aws:kms:us-east-2:111122223333:key/0987ab65-43cd-21ef-09ab-87654321cdef
$ key3=arn:aws:kms:ap-southeast-1:111122223333:key/1a2b3c4d-5e6f-1a2b-3c4d-5e6f1a2b3c4d

$ aws-encryption-cli --encrypt --input /logs/finance.log \
                               --output /archive --suffix \
                               --encryption-context class=log \
                               --metadata-output ~/metadata \
                               --wrapping-keys key=$key1 key=$key2 key=$key3
```

------
#### [ PowerShell ]

```
PS C:\> $key1 = 'arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'
PS C:\> $key2 = 'arn:aws:kms:us-east-2:111122223333:key/0987ab65-43cd-21ef-09ab-87654321cdef'
PS C:\> $key3 = 'arn:aws:kms:ap-southeast-1:111122223333:key/1a2b3c4d-5e6f-1a2b-3c4d-5e6f1a2b3c4d'

PS C:\> aws-encryption-cli --encrypt --input D:\Logs\Finance.log `
                           --output D:\Archive --suffix `
                           --encryption-context class=log `
                           --metadata-output $home\Metadata.txt `
                           --wrapping-keys key=$key1 key=$key2 key=$key3
```

------

這個命令會解密處理已加密的 `Finance.log` 檔案副本，並將其寫入 `Finance.log.clear` 目錄中的 `Finance` 檔案。若要解密在三下加密的資料 AWS KMS keys，您可以指定相同的三個 AWS KMS keys 或任何子集。此範例僅指定其中一個 AWS KMS keys。

若要告知 AWS 加密 CLI AWS KMS keys 使用哪個 來解密您的資料，請使用 `--wrapping-keys` 參數的**金鑰**屬性。使用 解密時 AWS KMS keys，**金鑰**屬性的值必須是[金鑰 ARN](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN)。

您必須擁有在您 AWS KMS keys 指定的 上呼叫 [Decrypt API](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html) 的許可。如需詳細資訊，請參閱 [的身分驗證和存取控制 AWS KMS](https://docs.aws.amazon.com/kms/latest/developerguide/control-access.html)。

最佳實務是，此範例使用 `--max-encrypted-data-keys` 參數來避免解密格式不正確的訊息，其中包含過多的加密資料金鑰。即使此範例僅使用一個包裝金鑰進行解密，加密的訊息具有三 (3) 個加密的資料金鑰；加密時使用的三個包裝金鑰各一個。指定預期的加密資料金鑰數量或合理的最大值，例如 5。如果您指定小於 3 的最大值，則命令會失敗。如需詳細資訊，請參閱[限制加密的資料金鑰](configure.md#config-limit-keys)。

------
#### [ Bash ]

```
$ aws-encryption-cli --decrypt --input /archive/finance.log \
                     --wrapping-keys key=$key1 \
                     --output /finance --suffix '.clear' \
                     --metadata-output ~/metadata \
                     --max-encrypted-data-keys 3 \
                     --buffer \
                     --encryption-context class=log
```

------
#### [ PowerShell ]

```
PS C:\> aws-encryption-cli --decrypt `
                           --input D:\Archive\Finance.log `
                           --wrapping-keys key=$key1 `
                           --output D:\Finance --suffix '.clear' `
                           --metadata-output .\Metadata\Metadata.txt `
                           --max-encrypted-data-keys 3 `
                           --buffer `
                           --encryption-context class=log
```

------

## 在指令碼中加密和解密
<a name="cli-example-script"></a>

此範例示範如何在指令碼中使用 AWS 加密 CLI。您可以編寫只要加密和解密資料的指令碼，或者在資料管理程序中負責加密或解密操作的指令碼。

在此範例中，指令碼會取得日誌檔案的集合、壓縮它們、加密它們，然後將加密的檔案複製到 Amazon S3 儲存貯體。這段指令碼會獨立處理個別檔案，所以這些檔案可以單獨地進行解密和展開。

在壓縮和加密檔案時，請務必先完成壓縮，再進行加密。正確完成加密的資料不能進行壓縮。

**警告**  
壓縮資料可能包含由惡意人士所操控的秘密和資料，請務必小心。壓縮資料的最終大小，可能會不當透露出與其內容有關的敏感資訊。

------
#### [ Bash ]

```
# Continue running even if an operation fails.
set +e

dir=$1
encryptionContext=$2
s3bucket=$3
s3folder=$4
masterKeyProvider="aws-kms"
metadataOutput="/tmp/metadata-$(date +%s)"

compress(){
    gzip -qf $1
}

encrypt(){
    # -e encrypt
    # -i input
    # -o output
    # --metadata-output unique file for metadata
    # -m masterKey read from environment variable
    # -c encryption context read from the second argument.
    # -v be verbose
    aws-encryption-cli -e -i ${1} -o $(dirname ${1}) --metadata-output ${metadataOutput} -m key="${masterKey}" provider="${masterKeyProvider}" -c "${encryptionContext}" -v
}


s3put (){
    # copy file argument 1 to s3 location passed into the script.
    aws s3 cp ${1} ${s3bucket}/${s3folder}
}

# Validate all required arguments are present.
if [ "${dir}" ] && [ "${encryptionContext}" ] && [ "${s3bucket}" ] && [ "${s3folder}" ] && [ "${masterKey}" ]; then

# Is $dir a valid directory?
test -d "${dir}"
if [ $? -ne 0 ]; then
    echo "Input is not a directory; exiting"
    exit 1
fi

# Iterate over all the files in the directory, except *gz and *encrypted (in case of a re-run).
for f in $(find ${dir} -type f \( -name "*" ! -name \*.gz ! -name \*encrypted \) ); do
    echo "Working on $f"
    compress ${f}
    encrypt ${f}.gz
    rm -f ${f}.gz
    s3put ${f}.gz.encrypted
done;
else
    echo "Arguments: <Directory> <encryption context> <s3://bucketname> <s3 folder>"
    echo " and ENV var \$masterKey must be set"
    exit 255
fi
```

------
#### [ PowerShell ]

```
#Requires -Modules AWSPowerShell, Microsoft.PowerShell.Archive
Param
(
    [Parameter(Mandatory)]
    [ValidateScript({Test-Path $_})]
    [String[]]
    $FilePath,

    [Parameter()]
    [Switch]
    $Recurse,

    [Parameter(Mandatory=$true)]
    [String]
    $wrappingKeyID,

    [Parameter()]
    [String]
    $masterKeyProvider = 'aws-kms',

    [Parameter(Mandatory)]
    [ValidateScript({Test-Path $_})]
    [String]
    $ZipDirectory,

    [Parameter(Mandatory)]
    [ValidateScript({Test-Path $_})]
    [String]
    $EncryptDirectory,

    [Parameter()]
    [String]
    $EncryptionContext,

    [Parameter(Mandatory)]
    [ValidateScript({Test-Path $_})]
    [String]
    $MetadataDirectory,

    [Parameter(Mandatory)]
    [ValidateScript({Test-S3Bucket -BucketName $_})]
    [String]
    $S3Bucket,

    [Parameter()]
    [String]
    $S3BucketFolder
)

BEGIN {}
PROCESS {
    if ($files = dir $FilePath -Recurse:$Recurse)
    {

        # Step 1: Compress
        foreach ($file in $files)
        {
            $fileName = $file.Name
            try
            {
                Microsoft.PowerShell.Archive\Compress-Archive -Path $file.FullName -DestinationPath $ZipDirectory\$filename.zip
            }
            catch
            {
                Write-Error "Zip failed on $file.FullName"
            }

            # Step 2: Encrypt
            if (-not (Test-Path "$ZipDirectory\$filename.zip"))
            {
                Write-Error "Cannot find zipped file: $ZipDirectory\$filename.zip"
            }
            else
            {
                # 2>&1 captures command output
                $err = (aws-encryption-cli -e -i "$ZipDirectory\$filename.zip" `
                                           -o $EncryptDirectory `
                                           -m key=$wrappingKeyID provider=$masterKeyProvider `
                                           -c $EncryptionContext `
                                           --metadata-output $MetadataDirectory `
                                           -v) 2>&1

                # Check error status
                if ($? -eq $false)
                {
                    # Write the error
                    $err
                }
                elseif (Test-Path "$EncryptDirectory\$fileName.zip.encrypted")
                {
                    # Step 3: Write to S3 bucket
                    if ($S3BucketFolder)
                    {
                        Write-S3Object -BucketName $S3Bucket -File "$EncryptDirectory\$fileName.zip.encrypted" -Key "$S3BucketFolder/$fileName.zip.encrypted"

                    }
                    else
                    {
                        Write-S3Object -BucketName $S3Bucket -File "$EncryptDirectory\$fileName.zip.encrypted"
                    }
                }
            }
        }
    }
}
```

------

## 使用資料金鑰快取
<a name="cli-example-caching"></a>

這個範例會在加密處理大量檔案的命令中使用[資料金鑰快取](data-key-caching.md)。

根據預設， AWS 加密 CLI （和其他版本的 AWS Encryption SDK) 會為其加密的每個檔案產生唯一的資料金鑰。雖然最佳加密實務是為每筆操作使用唯一的資料金鑰，但在某些情況下，仍可接受特定的資料金鑰重複使用。如果您考慮使用資料金鑰快取，請向安全性工程師諮詢實際應用上的安全性需求，並且決定適合您的安全性閾值。

在這個範例中，資料金鑰快取因為減少了向主金鑰提供者提出請求的頻率，使得加密操作速度加快。

在這個範例中的命令會加密處理包含多個子目錄的大型目錄，其中包含總共大約 800 個小型日誌檔。第一個命令會將 AWS KMS key 的 ARN 儲存在 `keyARN` 變數中。第二個命令會加密處理輸入目錄中的所有檔案，並將其寫入封存目錄。這個命令會使用 `--suffix` 參數來指定 `.archive` 尾碼。

`--caching` 參數會啟用資料金鑰快取。負責限制快取中資料金鑰數量的 **capacity** 屬性則設為 1，因為序列式檔案處理時，一次一律使用一個資料金鑰。負責決定已快取金鑰可以使用多久的 **max\$1age** 屬性則設為 10 秒鐘。

選用的 **max\$1messages\$1encrypted** 屬性則設為 10 則訊息，所以在加密處理 10 個以上的檔案時，絕對不會使用單一個資料金鑰。限定每個資料金鑰能夠加密的檔案數目，能在資料金鑰遭洩的難得情況發生時減少受到影響的檔案數量。

若要為作業系統產生的日誌檔執行這個命令，您可能需要具備系統管理員權限 (Linux 的 `sudo`；Windows 的 **Run as Administrator (以系統管理員身分執行)**)。

------
#### [ Bash ]

```
$  keyArn=arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab

$  aws-encryption-cli --encrypt \
                      --input /var/log/httpd --recursive \
                      --output ~/archive --suffix .archive \
                      --wrapping-keys key=$keyArn \
                      --encryption-context class=log \
                      --suppress-metadata \
                      --caching capacity=1 max_age=10 max_messages_encrypted=10
```

------
#### [ PowerShell ]

```
PS C:\> $keyARN = 'arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'

PS C:\> aws-encryption-cli --encrypt `
                           --input C:\Windows\Logs --recursive `
                           --output $home\Archive --suffix '.archive' `
                           --wrapping-keys key=$keyARN `
                           --encryption-context class=log `
                           --suppress-metadata `
                           --caching capacity=1 max_age=10 max_messages_encrypted=10
```

------

為了測試資料金鑰快取的效果，這個範例會在 PowerShell 中使用 [Measure-Command](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/measure-command) cmdlet。若執行此範例時不執行資料金鑰快取功能，完成需時大約 25 秒鐘。這個程序會為目錄中的每個檔案產生新的資料金鑰。

```
PS C:\> Measure-Command {aws-encryption-cli --encrypt `
                                            --input C:\Windows\Logs --recursive `
                                            --output $home\Archive  --suffix '.archive' `
                                            --wrapping-keys key=$keyARN `
                                            --encryption-context class=log `
                                            --suppress-metadata }


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 25
Milliseconds      : 453
Ticks             : 254531202
TotalDays         : 0.000294596298611111
TotalHours        : 0.00707031116666667
TotalMinutes      : 0.42421867
TotalSeconds      : 25.4531202
TotalMilliseconds : 25453.1202
```

資料金鑰快取能夠加快程序，即使限制每個資料金鑰最多只能處理 10 個檔案。這個命令現在只要不到 12 秒就能完成，因此向主金鑰提供者發出的呼叫次數減少成為原來次數的 1/10。

```
PS C:\> Measure-Command {aws-encryption-cli --encrypt `
                                            --input C:\Windows\Logs --recursive `
                                            --output $home\Archive  --suffix '.archive' `
                                            --wrapping-keys key=$keyARN `
                                            --encryption-context class=log `
                                            --suppress-metadata `
                                            --caching capacity=1 max_age=10 max_messages_encrypted=10}


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 11
Milliseconds      : 813
Ticks             : 118132640
TotalDays         : 0.000136727592592593
TotalHours        : 0.00328146222222222
TotalMinutes      : 0.196887733333333
TotalSeconds      : 11.813264
TotalMilliseconds : 11813.264
```

如果刪除 `max_messages_encrypted` 限制，則所有檔案都會依據相同的資料金鑰進行加密。這項變更會導致重複使用資料金鑰的風險提高，而且程序速度並不會加快。不過，它能將呼叫主金鑰提供者的次數縮減為 1 次。

```
PS C:\> Measure-Command {aws-encryption-cli --encrypt `
                                            --input C:\Windows\Logs --recursive `
                                            --output $home\Archive  --suffix '.archive' `
                                            --wrapping-keys key=$keyARN `
                                            --encryption-context class=log `
                                            --suppress-metadata `
                                            --caching capacity=1 max_age=10}


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 10
Milliseconds      : 252
Ticks             : 102523367
TotalDays         : 0.000118661304398148
TotalHours        : 0.00284787130555556
TotalMinutes      : 0.170872278333333
TotalSeconds      : 10.2523367
TotalMilliseconds : 10252.3367
```