0
votes

I want to use AWSKmsClient or AWS Encryption SDK with Java to decrypt the message I have encrypted using AWS CLI

I have created an encrypted message using:
aws kms encrypt --key-id 123421-4032-412c-4321-eds42d1a1b432 --plaintext MyText --output text --query CiphertextBlob
It generates something like this for me: ADCCAHhJotXoy8910T/Pd8PXVaF/Xkg+9NrF9QTy/XlW7rTtUAH6zACj9MbEY1cS7526GfscAAAAZjBkBgkqhkiG9w0BBwagVzBVAgEAMFAGCSqGSIb3DQEHATAeBglghkgBZDEEAS4wEQQMGmYHb67SV66h/eE0AgEQgCONMNda4kVsSi9sPAXXts2F0N/mwjSlIB2ngJcAyxymnltrHQ==

I want to pass this to my scala-spark code and decrypt it either with AWSKmsClient or AWS Encryption SDK with Java.

Based on this link it seems there some difference between AWS Encryption SDK and 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

I can not manage to do it with AWSKmsClient either, am I missing something? is there a better way to achieve this?

3
And I can not manage to do it with AWSKmsClient either any more details why you cannot decrypt the ciphertext with the kms client?gusto2

3 Answers

4
votes

The confusion here comes down to the difference between using AWS KMS directly via the AWS SDKs and using the AWS Encryption SDK.

The AWS Encryption SDK uses KMS (or other key providers) as part of an envelope encryption format[1]. Because of this, the snippet you quoted is correct: the output of the AWS Encryption SDK cannot be decrypted by KMS directly, and vice versa.

However, all AWS Encryption SDK implementations are compatible with each other.

If you want to encrypt something from the CLI that you can pass to Java/JVM code for decryption, that is definitely possible with the AWS Encryption SDK CLI and the AWS Encryption SDK for Java.

Source: I wrote the AWS Encryption SDK for Python[2] and CLI[3] and advised on the AWS Encryption SDK for C[4] as well as our documentation[5].


As for why you could not use AWSKmsClient to decrypt the value that you received from using the AWS CLI to call KMS directly, there are a variety of possibilities depending on what error you received.

One possibility is that you might not have Decrypt permissions on the CMK. This should have resulted in a permissions error from KMS.

Another possibility is that you are providing an invalid ciphertext. The AWS CLI automatically base64-encodes the CiphertextBlob binary data that it receives from KMS before returning it because most shells do not handle binary data well. However, AWSKmsClient will not automatically base64-decode anything before sending it to KMS. You must provide the raw bytes. So, if you are providing the base64-encoded string to AWSKmsClient in the decrypt request, then KMS will throw an error that you provided invalid ciphertext.

[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
votes

I have managed to use 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
  }

}
0
votes

"All language-specific implementations of the AWS Encryption SDK, including the AWS Encryption CLI, are interoperable." quoted from aws docs. so the missing link in your question body must contain false information.

there are basic examples in the documentation. Initing KmsMasterKeyProvider with your key id should do it for you.

Why don't you just wrap the encryption part in a java program which uses AWS Encryption SDK so you don't have to worry about 'Interoperability'?