Recently I published a post on AWS KMS encryption using .net / .net core. Now I got a chance to work on AWS KMS encryption using Node.Js. Following is the Node.Js version of the KMS helper class given in the previous post.
I used the aws-sdk npm for this
I used the aws-sdk npm for this
encrypt.js
'use strict';
var AWS = require("aws-sdk"),
crypto = require('crypto'),
algorithm = 'AES-256-CBC';
var awsconfig = {
"accessKey": "<Your AWS Access Key>",
"secretAccessKey": "<Your AWS Secret Key>",
"region": "<Your AWS region>",
"cmkArn": "<Your KMS master Key arn >" // The identifier of the CMK to use to encrypt the data key. You can use the key ID or Amazon Resource Name (ARN) of the CMK, or the name or ARN of an alias that refers to the CMK.
}
// Creates the KMS client
function getKMSClient() {
var credentials = new AWS.Credentials(awsconfig.accessKey, awsconfig.secretAccessKey);
AWS.config.update({
region: awsconfig.region,
credentials: credentials
});
return new AWS.KMS();
}
// Generates the KMS data Key
function generateDataKey() {
const kms = getKMSClient();
return new Promise((resolve, reject) => {
const params = {
KeyId: awsconfig.cmkArn,
KeySpec: 'AES_256'// Specifies the type of data key to return.
};
kms.generateDataKey(params, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
// Decrypt the KMS Data key
function decryptDataKey(CiphertextBlob) {
const kms = getKMSClient();
return new Promise((resolve, reject) => {
kms.decrypt({ CiphertextBlob }, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
module.exports = {
encrypt: function (text) {
return new Promise((resolve, reject) => {
generateDataKey().then(dataKey => {
// Get a random IV
const iv = crypto.randomBytes(16);
// Copy the length of the CiphertextBlob as first byte and concatenate the CiphertextBlob to it
var length = Buffer.from(['0x' + dataKey.CiphertextBlob.length.toString(16)]);
var str = Buffer.concat([length, dataKey.CiphertextBlob])
// Concatenate the iv to the buffer
str = Buffer.concat([str, iv]);
// Create aes encryptor with KMS plain key
var encryptor = crypto.createCipheriv(algorithm, dataKey.Plaintext, iv);
// Encrypt the data
encryptor.write(text);
encryptor.end();
// Concatenate the encrypted to the buffer and return the base64 string
str = Buffer.concat([str, encryptor.read()]);
resolve(str.toString('base64'));
}, error => {
reject(error);
});
});
},
decrypt: function (text) {
return new Promise((resolve, reject) => {
try {
// Convert the base64 string to buffer
var buf = Buffer.from(text, 'base64');
// Get the CiphertextBlob length stored in the firsty byte
var length = parseInt(buf[0].toString());
// Extract the CiphertextBlob, IV and
var cipherBlob = buf.slice(1, length+1);
var iv = buf.slice(length + 1, length + 1 + 16);
var encText = buf.slice(length + 1 + 16, buf.length);
// Decrypt the CiphertextBlob and get the plaintext key
decryptDataKey(cipherBlob).then(dataKey => {
// Create aes decryptor and decrypt the text
var decryptor = crypto.createDecipheriv(algorithm, dataKey.Plaintext, iv)
decryptor.write(encText);
decryptor.end();
resolve(decryptor.read().toString());
}, error => {
reject(error);
});
}
catch (err) {
reject(error);
}
});
}
}
routes.js
'use strict';
var express = require('express');
var kmsHelper = require('./encrypt');
var router = express.Router();
/* GET home page. */
router.get('/', function (req, res) {
res.render('home.html');
});
router.post('/api/encrypt', function (req, res) {
try {
kmsHelper.encrypt(req.body.text).then(result => {
res.send(result.toString());
}, err => {
res.statusCode = 404;
res.send(err);
});
}
catch (ex) {
res.statusCode = 404;
res.send(ex);
}
});
router.post('/api/decrypt', function (req, res) {
try {
kmsHelper.decrypt(req.body.text).then(result => {
res.send(result.toString());
}, err => {
res.statusCode = 404;
res.send(err);
});
}
catch (ex) {
res.statusCode = 404;
res.send(ex);
}
});
module.exports = router;
Happy Coding! 😊
0 comments:
Post a Comment