如何在不使用二进制文件的情况下调用Amazon的AWS KMS解密函数?

19

我有一个代码可以检索使用亚马逊的AWS KMS加密函数加密的字符串。我希望调用AWS KMS解密来获得未加密的值,但是我希望在不将该字符串写入二进制文件的情况下完成此操作。我找到的所有示例都假定您将使用Linux的base64命令或Windows的certutil命令将Base64编码的加密值转换为二进制文件。我正在尝试在Windows系统上执行此操作。我认为应该能够运行:

aws kms encrypt --key-id <mykey> --plaintext "mysecret"

对我来说,这产生了这个结果:

{
"KeyId": "arn:aws:kms:us-east-1:192491131326:key/<mykey>",
"CiphertextBlob": "AQICAHjQ7sViXQdeS4wWbFZpkOQWvCdNXqiy4Cnz0/xEBe39SQGz0vofeAo0+SyOXv172fqkAAAAZjBkBgkqhkiG9w0BBwagVzBVAgEAMFAGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMhchHh0ugGzwRTC4gAgEQgCMlkhYlCYk2SfYIkfQ6ruwA71KBcN7ih/OPzSE86OT/eBOz3Q=="
}

然后我应该就能够运行:

aws kms decrypt --ciphertext-blob AQICAHjQ7sViXQdeS4wWbFZpkOQWvCdNXqiy4Cnz0/xEBe39SQGz0vofeAo0+SyOXv172fqkAAAAZjBkBgkqhkiG9w0BBwagVzBVAgEAMFAGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMhchHh0ugGzwRTC4gAgEQgCMlkhYlCYk2SfYIkfQ6ruwA71KBcN7ih/OPzSE86OT/eBOz3Q==

为了获得结果。但迄今为止我除了以下内容以外什么也没得到:

An error occurred (InvalidCiphertextException) when calling the Decrypt operation:

是否有一组参数可以传递给解密命令,使其解密此字符串?


在您的示例中,返回的“CiphertextBlob”和传递的“--ciphertext-blob”是相似但不完全相同的值。 - Michael - sqlbot
我非常感到印象深刻,你注意到了这一点,但这只是我在组织问题时从多个来源复制时犯的错误,而不是问题的根源。我刚刚重复了测试,并验证了两个命令中的密文块是相同的,但我仍然得到了相同的错误。 - Bert Cushman
当我尝试和你一样的操作时,我也遇到了同样的错误。事实证明,您不能将certutil与kms decrypt命令组合使用。这就是为什么在官方文档中,我们需要保存Windows的二进制文件。https://docs.aws.amazon.com/cli/latest/reference/kms/decrypt.html - Ming M Zheng
4个回答

31

不确定您是否已经找到了这个,但是这似乎有效:

aws kms decrypt --ciphertext-blob fileb://<(echo "{YOUR CIPHERTEXTBLOB HERE}" | base64 -d) --output text --query Plaintext --region {REGION} | base64 -d

这是针对Mac的。在Windows上,我认为您需要使用 base64 -d。

希望这可以帮助到您。


8

我使用 aws kms 进行某项工作,因此希望能够处理流而不是文件。我在我的 shell 中定义了 2 个函数,也可以将它们放入脚本中。(我保留了分号,因为我已经将它们压缩成一行代码放在了我的 .bash_profile 中,但我喜欢在“教学”时将它们分开。)

export KMS_KEY=b31ef212-168e-4f7c-ab2a-fe8a623ee465

kmse(){
  local key=${1:-$KMS_KEY};
  aws kms encrypt \
    --key-id $key \
    --plaintext "$(cat /dev/stdin)" \
    --query CiphertextBlob \
    --output text;
}

kmsd(){
  aws kms decrypt \
    --ciphertext-blob fileb://<( \
      cat /dev/stdin | \
      sed 's/.*kmscrypt:://' | \
      tr -d '\n' | \
      base64 -D
    ) \
    --output text \
    --query Plaintext | \
  base64 -D;
}
kmse函数接受一个选项参数,该参数是要使用的密钥的UUID。否则,它将使用在KMS_KEY环境变量中指定的密钥。这两个函数都读取/dev/stdin以获取需要加密/解密的内容。因此,以下示例均可工作:
## Encrypting

$ tar -czf - /etc | kmse > etc.tgz.encrypted

$ kmse 77ed1d23-6013-47ce-b48a-2a968ef0ddaa < ~/.ssh/id_rsa > id_rsa.pem.encrypted

$ cat | kmse | netcat 10.0.0.123 8080
<content_pasted_from_my_clipboard>
^D

## Decrypting

$ kmsd < etc.tgz.encrypted | tar -zxf -

$ kmsd < id_rsa.pem.encrypted > ~/.ssh/id_rsa.pem

$ cat | kmsd | tee output.txt
<content_pasted_from_my_clipboard>
^D

# Note: ^D is a CTRL-D character that tells `cat` this is the End Of File.

虽然使用cat命令粘贴CTRL-D是个很酷的技巧。但我有一个名为 cb 的脚本, 可以通过标准输入/输出在我的剪贴板中获取和传输数据。而且,它现在可以在 Mac、Linux、Windows Cygwin 和 Windows WSL 上运行!因此,我可以使用以下命令对我的剪贴板中的内容进行加密和解密:

## Encrypt

$ cb | kmse | cb

## Decrypt

$ cb | kmsd | cb

一个类似的概念,只适用于Mac OSX:

## Encrypt

$ pbpaste | kmse | pbcopy

## Decrypt

$ pbpaste | kmsd | pbcopy

我在解密之前剥离了 kmscrypt::,因为有些来源会在base64编码的加密数据之前添加它。我怀疑这些来源来自或受到 https://gruntwork.io 的影响(而且总是尝试这样做是安全的,因为 :: 不是有效的 base64 并且不应该存在于那里)。 - Bruno Bronosky
如果不传递文件名,cat 命令会默认从标准输入读取数据,因此你甚至可以省略掉 /dev/stdin。 - toaster

0

我不知道是不是因为 AWS CLI v2 有什么变化,但这对我有效。

$ aws --version
aws-cli/2.11.3 Python/3.11.2 Darwin/22.3.0 source/arm64 prompt/off

我建议始终使用--region标志,以确保您正在使用所需区域的正确KMS密钥。

加密

$ aws kms encrypt --region us-east-1 --key-id alias/my-kms-key --plaintext "$(echo 'MY_SECRET_TO_ENCRYPT' | base64)"
{
    "CiphertextBlob": "AQICAHjmSj9FB9J0...",
    "KeyId": "arn:aws:kms:us-east-1:1234567890:key/...",
    "EncryptionAlgorithm": "SYMMETRIC_DEFAULT"
}

只需获取 CiphertextBlob

$ aws kms encrypt --region us-east-1 --key-id alias/my-kms-key --plaintext "$(echo 'MY_SECRET_TO_ENCRYPT' | base64)" --output text --query CiphertextBlob
AQICAHjmSj9FB9J0...

请注意,如果您对相同的字符串进行两次加密,则很可能会得到不同的CiphertextBlob,这是正常现象。
解密
$ aws kms decrypt --region us-east-1 --ciphertext-blob 'AQICAHjmSj9FB9J0...' --key-id alias/my-kms-key
{
    "KeyId": "arn:aws:kms:us-east-1:1234567890:key/...",
    "Plaintext": "TVlfU0VDUkVUX1RPX0VOQ1JZUFQK",
    "EncryptionAlgorithm": "SYMMETRIC_DEFAULT"
}

Plaintext以base64编码,因此需要解码:

$ echo 'TVlfU0VDUkVUX1RPX0VOQ1JZUFQK' | base64 -d
MY_SECRET_TO_ENCRYPT

要直接获取解码后的 明文

$ aws kms decrypt --region us-east-1 --ciphertext-blob 'AQICAHjmSj9FB9J0...' --key-id alias/my-kms-key --output text --query Plaintext | base64 -d
MY_SECRET_TO_ENCRYPT

我刚刚重复了我的初始问题的步骤,现在它可以工作了。我怀疑你说得对,AWS最近增强了某些功能,消除了对base64编码的需求。 - Bert Cushman

0
在Amazon Linux上解密
aws kms decrypt
     --ciphertext-blob "AQICAHjTIwSfITu1jx7fnG6XeOdEq/wgc7tOiGB+jW84ELp62wHTKddotXn/QbwoN0fW0Q....."     
     --key-id "alias/test-keys"
     --output text
     --query Plaintext | base64
     --decode > decrypted.txt

这应该可以工作。它解密了密码文本,并将明文解析到文件decrypted.txt中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接