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

时间:2019-04-23 19:55:32

标签: java scala amazon-web-services encryption aws-kms

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

基于this link,AWS Encryption SDK和AWS KMS之间似乎有些区别:

  

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

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

3 个答案:

答案 0 :(得分:1)

这里的困惑归结为直接通过AWS开发工具包使用AWS KMS和使用AWS Encryption SDK之间的区别。

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

但是,所有AWS Encryption SDK实现 彼此兼容

如果要通过CLI加密某些内容,然后可以传递给Java / JVM代码进行解密,那么使用AWS Encryption SDK CLI和适用于Java的AWS Encryption SDK绝对可以实现。

来源:我编写了适用于Python [2]和CLI [3]的AWS Encryption SDK,并就适用于C [4]的AWS Encryption 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

答案 1 :(得分:0)

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

documentation中有一些基本示例。使用您的密钥ID初始化KmsMasterKeyProvider应该可以为您完成。

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

答案 2 :(得分:0)

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

}