AWS Encryption CLI 的示例 - AWS Encryption SDK

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

AWS Encryption CLI 的示例

使用以下示例在首选平台上试用 AWS Encryption CLI。有关主密钥和其他参数的帮助,请参阅如何使用 AWS Encryption CLI。有关快速参考,请参阅 AWS Encryption SDK CLI 语法和参数参考

注意

以下示例使用 AWS Encryption CLI 版本 2.1.x 的语法。

新的安全功能最初是在 AWS Encryption 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 存储库中的相关安全通告

有关展示如何使用限制加密数据密钥的安全功能的示例,请参阅 限制加密数据密钥

有关展示如何使用 AWS KMS 多区域密钥的示例,请参阅 使用多区域 AWS KMS keys

加密文件

该示例使用 AWS Encryption CLI 加密 hello.txt 文件的内容,该文件中包含一个“Hello World”字符串。

在对一个文件运行加密命令时,AWS Encryption CLI 获取该文件的内容,生成唯一的数据密钥,使用该数据密钥加密文件内容,然后将加密的消息写入到新文件中。

第一个命令将 AWS KMS key 的密钥 ARN 保存在 $keyArn 变量中。使用 AWS KMS key 加密时,您可以使用密钥 ID、密钥 ARN、别名名称或别名 ARN 来识别该密钥。有关 AWS KMS key 密钥标识符的详细信息,请参阅《AWS Key Management Service 开发人员指南》中的密钥标识符

第二个命令加密文件内容。该命令使用 --encrypt 参数指定操作,并使用 --input 参数指示要加密的文件。--wrapping-keys 参数及其所需的 key 属性指示命令使用密钥 ARN 表示的AWS KMS key。

该命令使用 --metadata-output 参数指定一个包含有关加密操作的元数据的文本文件。作为最佳实践,该命令使用 --encryption-context 参数指定一个加密上下文

此命令还使用 --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)。由于加密命令没有为输出指定文件名,因此,AWS Encryption CLI 将输出写入到与输入文件具有相同名称并加上 .encrypted 后缀的文件。要使用不同的后缀或忽略后缀,请使用 --suffix 参数。

hello.txt.encrypted 文件包含加密的消息,其中包含 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

解密文件

该示例使用 AWS Encryption CLI 解密在上一示例中加密的 Hello.txt.encrypted 文件内容。

decrypt 命令使用 --decrypt 参数指示操作,并使用 --input 参数指定要解密的文件。--output 参数的值是一个句点,表示当前的目录。

带有 key 属性的 --wrapping-keys 参数指定用于解密加密消息的包装密钥。在使用 AWS KMS keys 的解密命令中,密钥属性的值必须是密钥 ARN。在解密命令中需要使用 --wrapping-keys 参数。如果您正在使用 AWS KMS keys,则可以使用 key 属性来指定 AWS KMS keys 用于解密,也可以使用值为 truediscovery 属性(但不能两者同时使用)。如果使用自定义主密钥提供程序,则需要使用 keyprovider 属性。

从版本 2.1.x 开始,--commitment-policy 参数是可选的,但建议使用。即使您指定了默认值 require-encrypt-require-decrypt,也可以明确使用该参数来明确您的意图。

--encryption-context 参数在 decrypt 命令中是可选的,即使在 encrypt 命令中提供了加密上下文。在这种情况下,decrypt 命令使用在 encrypt 命令中提供的相同加密上下文。在解密之前,AWS Encryption CLI 验证加密的消息中的加密上下文是否包含 purpose=test 对。如果不包含,decrypt 命令将失败。

--metadata-output 参数指定一个包含有关解密操作的元数据的文件。--output 参数的值“句点”(.) 指示将输出文件写入到当前目录中。

最佳实践是使用 --max-encrypted-data-keys 参数来避免使用过多的加密数据密钥解密格式错误的消息。指定预期的加密数据密钥数量(加密中使用的每个包装密钥各一个)或合理的最大值(例如 5)。有关详细信息,请参阅 限制加密数据密钥

只有在处理完所有输入之后,--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 后缀的新文件。要查看明文内容,请使用一个命令以获取文件内容,例如 catGet-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

加密目录中的所有文件

该示例使用 AWS Encryption CLI 加密目录中所有文件的内容。

如果一个命令影响多个文件,AWS Encryption CLI 将单独处理每个文件。它获取文件内容,从主密钥中获取文件的唯一数据密钥,使用该数据密钥加密文件内容,然后将结果写入到输出目录的新文件中。因此,您可以单独解密这些输出文件。

以下 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

第一个命令将 AWS KMS key 的 Amazon 资源名称(ARN)保存在 $keyArn 变量中。

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

--wrapping-keys 参数及其所需的 key 属性指定要使用的包装密钥。encrypt 命令包含一个加密上下文 (dept=IT)。如果在加密多个文件的命令中指定加密上下文,将在所有文件中使用相同的加密上下文。

该命令还具有一个 --metadata-output 参数,以指示 AWS Encryption CLI 在何处写入有关加密操作的元数据。AWS Encryption CLI 为加密的每个文件写入一个元数据记录。

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

在该命令完成时,AWS Encryption 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

解密目录中的所有文件

该示例解密目录中的所有文件。它从 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 目录中。带有 key 属性和密钥 ARN 值的 --wrapping-keys 参数指示 AWS Encryption CLI 使用哪个 AWS KMS keys 来解密文件。该命令使用 --interactive 参数指示 AWS Encryption CLI 在覆盖同名文件之前提示您。

该命令还使用在加密文件时提供的加密上下文。在解密多个文件时,AWS Encryption CLI 检查每个文件的加密上下文。如果任何文件上的加密上下文检查失败,AWS Encryption CLI 将拒绝该文件,写入一条警告,在元数据中记录失败,然后继续检查其余文件。如果 AWS Encryption CLI 由于任何其他原因无法解密文件,整个解密命令将立即失败。

在该示例中,所有输入文件中的加密消息包含 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

在命令行上加密和解密

以下示例介绍了如何通过管道将输入发送到命令 (stdin),以及将输出写入到命令行 (stdout)。这些示例说明了如何在命令中表示 stdin 和 stdout,以及如何使用内置的 Base64 编码工具防止 shell 错误地解释非 ASCII 字符。

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

该示例包含以下三个命令:

  • 第一个命令将 AWS KMS key 的密钥 ARN 保存在 $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 参数的 discovery 属性允许 AWS Encryption CLI 使用任何 AWS KMS key 来解密数据。该示例没有指定承诺策略,因此使用版本 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

使用多个主密钥

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

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

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

使用三个主密钥进行加密

该示例命令使用三个包装密钥加密 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 Encryption CLI 使用哪个 AWS KMS keys 来解密您的数据,请使用 --wrapping-keys 参数的 key 属性。使用 AWS KMS keys 解密时,key 属性的值必须是密钥 ARN

您必须有权在您指定的 AWS KMS keys 上调用 Decrypt API。有关更多信息,请参阅 AWS KMS 的身份验证和访问控制

作为最佳实践,该示例使用 --max-encrypted-data-keys 参数来避免使用过多的加密数据密钥来解密格式错误的消息。尽管该示例仅使用一个包装密钥进行解密,但加密的消息有三(3)个加密的数据密钥;加密时使用的三个包装密钥各有一个。指定预期的加密数据密钥数量或合理的最大值,例如 5。如果指定的最大值小于 3,则命令将失败。有关详细信息,请参阅 限制加密数据密钥

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

在脚本中加密和解密

此示例演示了如何在脚本中使用 AWS Encryption 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" } } } } } }

使用数据密钥缓存

该示例在加密大量文件的命令中使用数据密钥缓存

默认情况下,AWS Encryption CLI(和其他版本的 AWS Encryption SDK)为其加密的每个文件生成唯一的数据密钥。虽然在每个操作中使用唯一的数据密钥是加密最佳实践,但在某些情况下将数据密钥重用有限次数是可以接受的。如果考虑使用数据密钥缓存,请咨询安全工程师以了解您的应用程序的安全要求,并确定适合您的安全阈值。

在该示例中,数据密钥缓存降低发送到主密钥提供程序的请求频率以加快加密操作速度。

该示例中的命令加密一个具有多个子目录的大型目录,其中总共包含大约 800 个小日志文件。第一个命令将 AWS KMS key 的 ARN 保存在 keyARN 变量中。第二个命令加密输入目录中的所有文件(以递归方式),并将这些文件写入到存档目录中。该命令使用 --suffix 参数指定 .archive 后缀。

--caching 参数启用数据密钥缓存。capacity 属性(限制缓存中的数据密钥数)设置为 1,因为串行文件处理每次从不使用超过一个数据密钥。max_age 属性(确定可使用缓存的数据密钥的时间长度)设置为 10 秒。

可选的 max_messages_encrypted 属性设置为 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

要测试数据密钥缓存的效果,该示例在 PowerShell 中使用 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