0 votes
1 view
in AWS by (18.2k points)

I have a Lambda(NodeJS) function that writes data to DynamoDB. Some of that data needs to be encrypted. I'm encrypting using KMS encrypt and store. When I retrieve from Dynamo using a different Lambda function and try to decrypt, I get an error. If I encrypt and then turn around a decrypt, I'm able to do that, but if I'm reading the encrypted value from the DB, it won't decrypt. My encrypt/store code is below:

console.log('Loading event');

var AWS = require('aws-sdk');

var keyId = "arn:aws:kms:us-east-1:5423542542:key/xxxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxx";

var tableName = "person";

var dynamoDBConfiguration = {

    "region": "us-west-2"

};

AWS.config.update(dynamoDBConfiguration);

var dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

var kms = new AWS.KMS({region: 'us-east-1'});

var newId = "1234-56789-101112-13141516";

var item = {};

exports.handler = function (event, context) {

    console.log('ssn');

    //encrypt it

    var ssnParams = {

        KeyId: keyId,

        Plaintext: "123-45-6789"

    };

    kms.encrypt(ssnParams, function (err, data) {

        if (err) {

            console.log(err, err.stack);

        }

        else {

            console.log(' ssn encrypted');

            var enc_ssn = data.CiphertextBlob;

            item["SSN"] = {"Value": {"B": enc_ssn}};

            item["First_Name"] = {"Value": {"S": "Joe"}};

            item["Last_Name"] = {"Value": {"S": "Blow"}};

            dynamodb.updateItem({

                "TableName": tableName,

                "AttributeUpdates": item,

                "ReturnValues": "ALL_NEW",

                "Key": {

                    "id": {"S": newId}

                }

            }, function (err, data) {

                if (err) {

                    context.done(err);

                }

                else {

                    console.log('great success: %j', data);

                    context.succeed("Person Successfully Inserted");

                }

            });

        }

    });

};

My retrieval/decrypt code is as follows:

console.log('Loading event');

var AWS = require('aws-sdk');

var dynamoDBConfiguration = {

    "region": "us-west-2"

};

AWS.config.update(dynamoDBConfiguration);

var dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

var keyId = "arn:aws:kms:us-east-1:5423542542:key/xxxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxx";

var tableName = "person";

var kms = new AWS.KMS({region: 'us-east-1'});

exports.handler = function (event, context) {

    console.log(JSON.stringify(event, null, '  '));

    var params = {};

    var id = event.id;

    console.log(id);

    if (id && id !== '') {

        params = {

            "TableName": tableName,

            KeyConditionExpression: "id = :id",

            ExpressionAttributeValues: {

                ':id': {'S': id}

            }

        };

        dynamodb.query(params, function (err, data) {

            if (err) {

                context.done(err);

            }

            else {

                var person = data.Items[0];

                console.log('query success');

                console.log(person);

                if (person.SSN) {

                    console.log('have ssn');

                    var b_ssn = person.SSN;

                    console.log(b_ssn);

                    person.SSNtext = "";

                    var encryptedParams = {

                        CiphertextBlob: Buffer(b_ssn, 'base64'),

                    };

                    kms.decrypt(encryptedParams, function (err, decrypteddata) {

                        if (err) {

                            console.log(err, err.stack);

                            //context.done(err);

                        }

                        else {

                            person.SSNtext = decrypteddata.Plaintext.toString();

                            console.log(decrypteddata.Plaintext.toString());

                            context.succeed(person);

                        }

                    });

                }

            }

        });

    }

    else {

        params = {

            "TableName": tableName

        };

        dynamodb.scan(params, function (err, data) {

            if (err) {

                context.done(err);

            }

            else {

                console.log('scan success');

                context.succeed(data);

            }

        });

    }

};

When I run this code, I get the following error:

START RequestId: 639590ac-cb95-11e5-91e4-d706c725f529 Version: $LATEST

2016-02-04T23:16:58.713Z    639590ac-cb95-11e5-91e4-d706c725f529    Loading event

2016-02-04T23:17:00.215Z    639590ac-cb95-11e5-91e4-d706c725f529    {

  "id": "1234-56789-101112-13141516"

}

2016-02-04T23:17:00.215Z    639590ac-cb95-11e5-91e4-d706c725f529    1234-56789-101112-13141516

2016-02-04T23:17:00.954Z    639590ac-cb95-11e5-91e4-d706c725f529    query success

2016-02-04T23:17:00.954Z    639590ac-cb95-11e5-91e4-d706c725f529    { Last_Name: { S: 'Blow' },

  id: { S: '1234-56789-101112-13141516' },

  First_Name: { S: 'Joe' },

  SSN: { B: <Buffer 0a 20 ec 00 75 21 f2 61 7d ba 2e 38 7e c6 fd 24 6d 32 b4 c2 b3 29 47 9e 9b 97 f2 a8 46 f2 d0 38 da 37 12 92 01 01 01 02 00 78 ec 00 75 21 f2 61 7d ba 2e ...> } }

2016-02-04T23:17:00.956Z    639590ac-cb95-11e5-91e4-d706c725f529    have ssn

2016-02-04T23:17:00.956Z    639590ac-cb95-11e5-91e4-d706c725f529    { B: <Buffer 0a 20 ec 00 75 21 f2 61 7d ba 2e 38 7e c6 fd 24 6d 32 b4 c2 b3 29 47 9e 9b 97 f2 a8 46 f2 d0 38 da 37 12 92 01 01 01 02 00 78 ec 00 75 21 f2 61 7d ba 2e ...> }

2016-02-04T23:17:01.573Z    639590ac-cb95-11e5-91e4-d706c725f529    { [InvalidCiphertextException: null]

  message: null,

  code: 'InvalidCiphertextException',

  time: Thu Feb 04 2016 23:17:01 GMT+0000 (UTC),

I can encrypt and decrypt the encrypted value, but when I store the value, retrieve it and try to decrypt it, it fails. Any help would be greatly appreciated.

1 Answer

0 votes
by (42.5k points)

I got it. When you store data into a DynamoDB, you use something like this:

item["First_Name"] = {"Value":{"S": "Joe"}};

When I retrieved it, instead of a string I got an object. So the mistake was, instead of passing the value, I passed the object.

first_name = person.First_Name.S;

//results in first_name = "Joe";

So the issue I was having is that I was trying to pass the object person.First_Name to the decrypt method and not the value of person.First_Name.S

Welcome to Intellipaat Community. Get your technical queries answered by top developers !


Categories

...