如何使用带有 Java 或 AWSKmsClient 的 AWS 加密 SDK 解密 AWS KMS 密码

How to decrypt AWS KMS cipher with AWS Encryption SDK with Java or AWSKmsClient

我想将 AWSKmsClient 或 AWS 加密 SDK 与 Java 一起使用来解密我使用 AWS CLI

加密的消息

我使用以下方法创建了一条加密消息:
aws kms encrypt --key-id 123421-4032-412c-4321-eds42d1a1b432 --plaintext MyText --output text --query CiphertextBlob
它为我生成了这样的东西: ADCCAHhJotXoy8910T/Pd8PXVaF/Xkg+9NrF9QTy/XlW7rTtUAH6zACj9MbEY1cS7526GfscAAAAZjBkBgkqhkiG9w0BBwagVzBVAgEAMFAGCSqGSIb3DQEHATAeBglghkgBZDEEAS4wEQQMGmYHb67SV66h/eE0AgEQgCONMNda4kVsSi9sPAXXts2F0N/mwjSlIB2ngJcAyxymnltrHQ==

我想将其传递给我的 scala-spark 代码并使用 AWSKmsClient 或 AWS 加密 SDK 和 Java.

对其进行解密

基于this link,似乎 AWS 加密 SDK 和 AWS KMS 之间存在一些差异:

The AWS Encryption SDK for Java is not meant to be compatible with the aws kms command line tool. In short, the AWS Encryption SDK leverages KMS to provide more versatile encryption functionality than KMS alone

我也无法使用 AWSKmsClient 做到这一点,我是不是遗漏了什么?有没有更好的方法来实现这一点?

"All language-specific implementations of the AWS Encryption SDK, including the AWS Encryption CLI, are interoperable." 引自 aws docs。所以你的问题正文中缺失的 link 一定包含虚假信息。

documentation. Initing KmsMasterKeyProvider 中有基本示例,您的密钥 ID 应该可以为您完成。

为什么不将加密部分包装在使用 AWS 加密 SDK 的 java 程序中,这样您就不必担心 'Interoperability'?

这里的混淆归结为直接通过 AWS SDK 使用 AWS KMS 和使用 AWS 加密 SDK 之间的区别。

AWS 加密 SDK 使用 KMS(或其他密钥提供程序)作为信封加密格式的一部分[1]。因此,您引用的片段是正确的:AWS 加密 SDK 的输出不能直接被 KMS 解密,反之亦然。

但是,所有 AWS 加密 SDK 实施相互兼容

如果您想从 CLI 加密某些内容,然后将其传递给 Java/JVM 代码进行解密,这绝对可以使用 AWS 加密 SDK CLI 和适用于 Java 的 AWS 加密 SDK。

资料来源:我为 Python[2] 和 CLI[3] 编写了 AWS 加密 SDK,并为 C[4] 的 AWS 加密 SDK 以及我们的文档[5] 提供了建议。


至于为什么您不能使用 AWSKmsClient 解密您使用 AWS CLI 直接调用 KMS 收到的值,有多种可能性,具体取决于您收到的错误。

一种可能是您可能没有 CMK 的 Decrypt 权限。这应该导致 KMS 出现权限错误。

另一种可能是您提供的密文无效。 AWS CLI 在返回之前自动对从 KMS 接收的 CiphertextBlob 二进制数据进行 base64 编码,因为大多数 shell 不能很好地处理二进制数据。但是,AWSKmsClient 不会在将任何内容发送到 KMS 之前自动对其进行 base64 解码。您必须提供原始字节。因此,如果您在解密请求中向 AWSKmsClient 提供 base64 编码的字符串,则 KMS 将抛出一个错误,指出您提供了无效的密文。

[1] https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html

[2] https://aws-encryption-sdk-python.readthedocs.io/en/latest/

[3]https://aws-encryption-sdk-cli.readthedocs.io/en/latest/

[4]https://github.com/awslabs/aws-encryption-sdk-c

[5]https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/introduction.html

我已经成功使用 AWSKMSClient

import java.nio.charset.StandardCharsets

import com.amazonaws.services.kms.{AWSKMS, AWSKMSClientBuilder}
import com.amazonaws.services.kms.model.DecryptRequest
import java.nio.ByteBuffer
import com.google.common.io.BaseEncoding

object KMSUtils {

  val keyId = "arn:aws:kms:us-east-1:{Account ID}:key/{KEY ID}"

  def decrypt(base64EncodedValue: String): String = {
    val kmsClient: AWSKMS = AWSKMSClientBuilder.standard.build

    val textDecoded: ByteBuffer = ByteBuffer.wrap(BaseEncoding.base64().decode(base64EncodedValue))

    val req : DecryptRequest = new DecryptRequest().withCiphertextBlob(textDecoded)
    val plainText : ByteBuffer = kmsClient.decrypt(req).getPlaintext

    val printable = StandardCharsets.UTF_8.decode(plainText).toString

    return printable
  }

}