

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 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 加密 CLI 版本为 1.8。 *x* 取代了 1.7 版。 *x* 和 AWS 加密 CLI 2.1。 *x* 取代 2.0。 *x*。有关详细信息，请参阅[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) GitHub。

有关展示如何使用限制加密数据密钥的安全功能的示例，请参阅 [限制加密数据密钥](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 Encryption CLI 会获取文件内容，生成唯一[的数据密钥](concepts.md#DEK)，加密数据密钥下的文件内容，然后将[加密的消息](concepts.md#message)写入新文件。

第一个命令将的密钥 ARN 保存在变量 AWS KMS key 中。`$keyArn`使用加密时 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 .
```

------

如果 encrypt 命令成功，它不返回任何输出。要确定该命令是否成功，请检查 `$?` 变量中的布尔值。命令成功后，的值`$?`为 `0` (Bash) 或 `True` (PowerShell)。命令失败时，的值`$?`为非零 (Bash) 或 `False` (PowerShell)。

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

```
$ echo $?
0
```

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

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

------

也可以使用目录列表命令查看 encrypt 命令是否创建了新的文件 (`hello.txt.encrypted`)。由于 encrypt 命令没有为输出指定文件名，因此 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 命令使用 `--decrypt` 参数指示操作，并使用 `--input` 参数指定要解密的文件。`--output` 参数的值是一个句点，表示当前的目录。

带有 **key** 属性的 `--wrapping-keys` 参数指定用于解密加密消息的包装密钥。在使用解密命令中 AWS KMS keys，密钥属性的值必须是密钥 [AR](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN) N。在解密命令中需要使用 `--wrapping-keys` 参数。如果您正在使用 AWS KMS keys，则可以使用 **key** 属性来指定 AWS KMS keys 用于解密，也可以使用值为 `true` 的 **discovery** 属性（但不能两者同时使用）。如果使用自定义主密钥提供程序，则需要使用 **key** 和 **provider** 属性。

从版本 2.1.*x* 开始，[`--commitment-policy` 参数](crypto-cli-reference.md#syntax-commitment-policy)是可选的，但建议使用。即使您指定了默认值 `require-encrypt-require-decrypt`，也可以明确使用该参数来明确您的意图。

`--encryption-context` 参数在 decrypt 命令中是可选的，即使在 encrypt 命令中提供了[加密上下文](crypto-cli-how-to.md#crypto-cli-encryption-context)。在这种情况下，decrypt 命令使用在 encrypt 命令中提供的相同加密上下文。在解密之前，Encryption CL AWS I 会验证加密消息中的加密上下文是否包含一对。`purpose=test`如果不包含，decrypt 命令将失败。

`--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 .
```

------

如果 decrypt 命令成功，它不返回任何输出。要确定该命令是否成功，请获取 `$?` 变量值。也可以使用目录列表命令查看该命令是否创建了具有 `.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 资源名称 (ARN)](https://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html#find-cmk-id-arn) 保存在变量 AWS KMS key 中。`$keyArn`

第二个命令加密 `TestDir` 目录中的文件内容，并将包含加密内容的文件写入到 `TestEnc` 目录中。如果 `TestEnc` 目录不存在，该命令将失败。由于输入位置是一个目录，因此，`--recursive` 参数是必需的。

[`--wrapping-keys` 参数](crypto-cli-how-to.md#crypto-cli-master-key)及其所需的 **key** 属性指定要使用的包装密钥。encrypt 命令包含一个[加密上下文](crypto-cli-how-to.md#crypto-cli-encryption-context) (`dept=IT`)。如果在加密多个文件的命令中指定加密上下文，将在所有文件中使用相同的加密上下文。

该命令还有一个`--metadata-output`参数，用于告诉 AWS Encryption CLI 在哪里写入有关加密操作的元数据。加 AWS 密 CLI 为每个加密文件写入一条元数据记录。

从版本 2.1.*x* 开始，[`--commitment-policy parameter`](crypto-cli-how-to.md#crypto-cli-commitment-policy) 是可选的，但建议使用。如果命令或脚本因无法解密加密文字而失败，则显式承诺策略设置可以帮助您快速检测问题。

命令完成后， AWS 加密 CLI 会将加密文件写入该`TestEnc`目录，但不会返回任何输出。

最后一个命令列出 `TestEnc` 目录中的文件。每个包含明文内容的输入文件具有一个包含加密内容的输出文件。由于该命令未指定替代后缀，因此，encrypt 命令将 `.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
```

------

此 decrypt 命令解密目录中的所有文件，并将纯文本文件写入该 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 Encryption CLI 会拒绝该文件，写入警告，在元数据中记录失败，然后继续检查其余文件。如果 AWS 加密 CLI 由于任何其他原因无法解密文件，则整个 decrypt 命令将立即失败。

在该示例中，所有输入文件中的加密消息包含 `dept=IT` 加密上下文元素。不过，如果解密的消息具有不同的加密上下文，您仍然可以验证加密上下文部分。例如，如果某些消息具有 `dept=finance` 加密上下文，而其他消息具有 `dept=IT` 加密上下文，您可以确认加密上下文始终包含未指定值的 `dept` 名称。如果要了解更具体的信息，您可以在单独的命令中解密这些文件。

decrypt 命令不返回任何输出，但您可以使用目录列表命令查看它是否创建了具有 `.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 字符。

该示例通过管道将明文字符串发送到 encrypt 命令，并将加密的消息保存在变量中。然后，它通过管道将变量中的加密消息发送到 decrypt 命令，后者将其输出写入到管道中 (stdout)。

该示例包含以下三个命令：
+ 第一个命令将的[密钥 ARN](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN) 保存在变量 AWS KMS key 中。`$keyArn`

------
#### [ 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` 字符串发送到 encrypt 命令，并将结果保存在 `$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` 变量中的加密消息发送到 decrypt 命令。

  该 decrypt 命令使用 `--input -` 指示输入来自于管道 (stdin)，并使用 `--output -` 将输出发送到管道 (stdout)。（input 参数使用输入位置而不是实际输入字节，因此，您不能将 `$encrypted` 变量作为 `--input` 参数值。） 

  此示例使用`--wrapping-keys`参数的**发现**属性允许 AWS Encryption CLI 使用任何属性 AWS KMS key 来解密数据。该示例没有指定[承诺策略](concepts.md#commitment-policy)，因此使用版本 2.1.*x* 及更高版本的默认值 `require-encrypt-require-decrypt`。

  由于输出已加密并随后进行编码，因此，decrypt 命令在解密 Base64 编码的输入之前使用 `--decode` 参数对其进行解码。您也可以在加密 Base64 编码的输入之前使用 `--decode` 参数对其进行解码。

  同样，该命令省略加密上下文并忽略元数据 (-`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>

此示例说明如何在加密 CLI 中加密和解密数据时使用多个主密钥。 AWS 

在使用多个主密钥加密数据时，可以使用任何一个主密钥解密数据。该策略确保您始终可以解密数据，即使某个主密钥不可用。如果您要将加密的数据存储在多个中 AWS 区域，则此策略允许您在同一区域使用主密钥来解密数据。

在使用多个主密钥进行加密时，第一个主密钥起到特殊的作用。它生成用于加密数据的数据密钥。其余主密钥加密明文数据密钥。生成的[加密消息](concepts.md#message)包含加密的数据以及加密的数据密钥集合，每个主密钥具有一个加密的数据密钥。虽然数据密钥是第一个主密钥生成的，但任何主密钥都可以解密其中的一个数据密钥，这些数据密钥可用于解密数据。

**使用三个主密钥进行加密**

该示例命令使用三个包装密钥加密 `Finance.log` 文件，在三个 AWS 区域中各具有一个包装密钥。

它将加密的消息写入到 `Archive` 目录中。该命令使用没有值的 `--suffix` 参数以忽略后缀，因此，输入和输出文件名称是相同的。

该命令使用具有三个 **key** 属性的 `--wrapping-keys` 参数。您也可以在同一命令中使用多个 `--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，密**钥属性的值必须是密钥** [AR](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN) N。

您必须有权在 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 Encryption 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 系统中的**以管理员身份运行**）。

------
#### [ 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
```

------

为了测试数据密钥缓存的效果，此示例在中使用了 Measu [re-Command cmdlet](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/measure-command)。 PowerShell如果运行该示例而不使用数据密钥缓存，大约需要 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
```