Search code examples
node.jsamazon-web-servicesencryptionbase64amazon-kms

Why is my AWS KMS decrypt not giving me back the string I just encrypted?


Here is my code:

const AWS = require('aws-sdk');
const btoa = require('btoa');

let kms = new AWS.KMS({
    accessKeyId: 'redacted',
    secretAccessKey: 'redacted',
    region: 'us-east-1'
});

let params = {
    KeyId: 'redacted',
    Plaintext: 'abcde'
 };

let encrypted = kms.encrypt(params, function(err, data) {
    if (err) console.log(err, err.stack); // an error occurred
    else {
        let x = {
            CiphertextBlob: data.CiphertextBlob
        };

        kms.decrypt(x, function(err, data) {
            if (err) console.log(err, err.stack); // an error occurred
            else     console.log(btoa(data.Plaintext));           // successful response
        });
    }
 });

I am just trying to encrypt the string abcde and then decrypt it, but this is not working. For awhile I was getting InvalidCipherException, but now the output of console.log(btoa(data.Plaintext)); is YWJjZGU=.

I cannot fathom what I'm doing wrong here but I suspect it has to do with base64 encoding. I have tried so many variants on this code but cannot deduce the problem. Does anyone see what I'm doing wrong here?


Solution

  • I was using btoa when I should have been using atob. I would swear I already tried that, but who can say.

    Since I thought atob was ASCII to Binary, I can't account for how I'm getting plaintext with a function that's supposed to give binary, but...it worked, so.

    Edit: Thinking of it as ASCII to Binary is misleading. It's more like "transmission format" to "original content," whatever that content was.

    The KMS.decrypt method wants a binary string, which is the "original content" here. KMS.encrypt base64-encoded the encrypted string for transmission, and KMS.decrypt expects it to be coded out of that format before being given as a parameter.