0

So I've been reading and reading and looking at examples and...failing miserably. Here's my situation:

I have a CMK in KMS and I've generated a data key, like so:

$ aws kms generate-data-key --key-id 64a62e3e-7e38-4f86-8ef2-3d00929e6260 --key-spec AES_256
{
   "Plaintext": "+SjeaxtD5TIhOcY16+A2NA493MbxnYozbzZx4i3/BfA=", 
   "KeyId": "arn:aws:kms:us-west-2:040512153658:key/64a62e3e-7e38-4f86-8ef2-3d00929e6260", 
   "CiphertextBlob": "AQIDAHgrvfqfgn9D0tTUJOISzFCz7ejMPZ6/HGX0kGAlzKYZ7wEiyHdpuGaOjpq4UQazPAgeAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMU5JtbI6lxLOv/p4KAgEQgDsX97Pk+ywqLU2VymLRgDSz0exOyzRgLMgd7WEf3sLUh4GnbYllIrxNSdK/DSZrYUhBo78KYugnkTj89g=="
}

I then verify it by decrypting from the CLI:

$ aws kms decrypt --ciphertext-blob fileb://<(echo 'AQIDAHgrvfqfgn9D0tTUJOISzFCz7ejMPZ6/HGX0kGAlzKYZ7wEiyHdpuGaOjpq4UQazPAgeAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMU5JtbI6lxLOv/p4KAgEQgDsX97Pk+ywqLU2VymLRgDSz0exOyzRgLMgd7WEf3sLUh4GnbYllIrxNSdK/DSZrYUhBo78KYugnkTj89g==' | base64 -d) --query Plaintext
"+SjeaxtD5TIhOcY16+A2NA493MbxnYozbzZx4i3/BfA="

Lo and behold! I get the Plaintext value back all nice and clean. I then try to grind that same ciphertext blob through the SDK using Java with the following code:

    .
    .
    .
    final String encryptedCipherText = "AQIDAHgrvfqfgn9D0tTUJOISzFCz7ejMPZ6/HGX0kGAlzKYZ7wEiyHdpuGaOjpq4UQazPAgeAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMU5JtbI6lxLOv/p4KAgEQgDsX97Pk+ywqLU2VymLRgDSz0exOyzRgLMgd7WEf3sLUh4GnbYllIrxNSdK/DSZrYUhBo78KYugnkTj89g==";
    final String expectedPlainText = "+SjeaxtD5TIhOcY16+A2NA493MbxnYozbzZx4i3/BfA=";

    AWSKMS kmsClient;
    String returnValue;

    kmsClient = AWSKMSClientBuilder
            .standard()
            .withRegion("us-west-2")
            .build();

    ByteBuffer cipherTextBlob = ByteBuffer.wrap(Base64.getDecoder().decode(encryptedCipherText));
    DecryptRequest decryptRequest = new DecryptRequest().withCiphertextBlob(cipherTextBlob);
    ByteBuffer key = kmsClient.decrypt(decryptRequest).getPlaintext();
    final byte[] bytes = new byte[key.remaining()];
    key.duplicate().get(bytes);
    String result = new String(bytes);
    if (expectedPlainText.equals(result)) {
        LOG.info("decrypted plaintext matches expected");
    } else {
        LOG.error("decrypted plaintext unexpected value: " + result);
    }
    .
    .
    .

And the LOG entry dumped out was:

23:08:33.210 [main] ERROR com.eyefinity.magicmissile.aws.AwsClientConfig - decrypted plaintext unexpected value: �(�k�2!9�5��64=���3o6q�-��

I've tried encoding the result with every Charset available to me, and no Charset produces my original Plaintext key. As near as I can tell from all the examples I've seen, my code is correct. So what am I doing wrong or what am I missing here? All I want is to end up with a Java String variable that contains "+SjeaxtD5TIhOcY16+A2NA493MbxnYozbzZx4i3/BfA=".

RobA
  • 368
  • 2
  • 10
  • Can you try `StandardCharsets.UTF_8.decode(key).toString()` to convert `ByteBuffer key` to `String`? – ketan vijayvargiya Oct 03 '17 at 20:37
  • Because I don't see any issues with other parts of your code. If there were, the KMS-client itself would've threw up. – ketan vijayvargiya Oct 03 '17 at 20:45
  • I tried `new String(bytes, Charset.forName("UTF-8")` with no luck, but I'll give your suggestion a try. – RobA Oct 04 '17 at 16:00
  • `16:02:40.885 [main] ERROR com.eyefinity.magicmissile.aws.AwsClientConfig - decrypted plaintext unexpected value: �(�k�2!9�5��64=���3o6q�-��` Different encoded value, but still not what I was looking for. – RobA Oct 04 '17 at 16:03
  • The more I look at this (and debug through the SDK code) the more I believe the problem is in the response values being stored in a HeapByteBuffer and my attempts to translate those back to Strings. I can see the HTTP response from a GenerateDataKey request that the values coming back are what I'd expect, but by the time I've grabbed them out of the result object and try to convert them to String, they're all garbled. – RobA Oct 04 '17 at 18:55
  • e.g. this is from the logs of a test that generates a data key and tries to decrypt the ciphertextblob: `11:49:09.748 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "{"CiphertextBlob":"AQIDAHgrvfqfgn9D0tTUJOISzFCz7ejMPZ6/HGX0kGAlzKYZ7wEsvlr67VIip9l2h6/YMFL/AAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMbzydNXgLJPcHxmn7AgEQgDvQEqaTOf4yuFz38fzm6f8cTVt0oCOOLo+d5xJf4BjflpIBYDyD+dlbjKCAJ93x1PvDRcKWexWWOEMAYQ==","KeyId":"arn:aws:kms:us-west-2:040512153658:key/64a62e3e-7e38-4f86-8ef2-3d00929e6260","Plaintext":"aICC7m772pnZC0L2OlUfxOdf8BSvhqj/CAjZI0SpTrA="}"` – RobA Oct 04 '17 at 18:57
  • I agree. If the input to the `decrypt` function was bad, KMS would have thrown up an error on the lines of 'could not decrypt input'. The fact that it didn't means it *could* decrypt the input, just that you are unable to read it back. – ketan vijayvargiya Oct 04 '17 at 20:13
  • Is there a way to specify encryption algorithm, AES_256, somewhere? – ketan vijayvargiya Oct 04 '17 at 20:13
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/155964/discussion-between-ketan-vijayvargiya-and-roba). – ketan vijayvargiya Oct 04 '17 at 20:13

1 Answers1

1

I stumbled on my own solution: I was SO CLOSE! All that's required in the code above to extract the same Plaintext value that is returned from KMS, and the ASCII string I received on the aws-cli command line when generating the datakey, is to take the byte array and Base64 encode it. So referencing my sample code above, all the way at the top, replace the line that reads...

String result = new String(bytes);

with something like this:

String result = Base64.getEncoder().encodeToString(bytes);
RobA
  • 368
  • 2
  • 10