0

我想使用 AWSKmsClient 或 AWS Encryption 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 或使用 Java 的 AWS 加密 SDK 对其进行解密。

基于此链接,AWS Encryption SDK 和 AWS KMS 之间似乎存在一些差异:

适用于 Java 的 AWS 加密开发工具包并不意味着与 aws kms 命令行工具兼容。简而言之,AWS 加密 SDK 利用 KMS 提供比单独使用 KMS 更通用的加密功能

我也无法用 AWSKmsClient 做到这一点,我错过了什么吗?有没有更好的方法来实现这一目标?

4

3 回答 3

5

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

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

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

如果您想从 CLI 加密一些可以传递给 Java/JVM 代码进行解密的内容,那么使用 AWS Encryption SDK CLI 和适用于 Java 的 AWS Encryption SDK 绝对可以实现。

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


至于为什么您无法使用AWSKmsClientAWS CLI 直接调用 KMS 来解密您收到的值,根据您收到的错误有多种可能性。

一种可能性是您可能没有DecryptCMK 的权限。这应该会导致来自 KMS 的权限错误。

另一种可能性是您提供的密文无效。AWS CLI 在返回之前自动对从 KMS 接收的二进制数据进行 base64 编码CiphertextBlob,因为大多数 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

于 2019-04-24T21:25:24.593 回答
1

我已经设法使用 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
  }

}
于 2019-04-25T19:11:16.017 回答
0

“AWS Encryption SDK 的所有特定语言的实施,包括 AWS Encryption CLI,都是可互操作的。” 引用自aws 文档。因此,您的问题正文中缺少的链接必须包含虚假信息。

文档中有基本示例。使用您的密钥 ID初始化 KmsMasterKeyProvider应该会为您完成。

为什么不将加密部分包装在使用 AWS 加密 SDK 的 java 程序中,这样您就不必担心“互操作性”?

于 2019-04-24T15:44:29.420 回答