simple-aes
Version:
Simple abstraction of AES to ensure no silly mistakes
172 lines (130 loc) • 5.79 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _crypto = require('crypto');
var _crypto2 = _interopRequireDefault(_crypto);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var KEY_SYM = Symbol('key');
var BITS_IN_BYTE = 8;
var BLOCK_SIZE = 16; // 128 bits
var SimpleAES = function () {
function SimpleAES(keyLength, key) {
_classCallCheck(this, SimpleAES);
if (!(keyLength === 128 || keyLength === 192 || keyLength === 256)) {
throw new TypeError('Value of argument "keyLength" violates contract.\n\nExpected:\n128 | 192 | 256\n\nGot:\n' + _inspect(keyLength));
}
if (!(typeof key === 'string' || key instanceof Buffer)) {
throw new TypeError('Value of argument "key" violates contract.\n\nExpected:\nstring | Buffer\n\nGot:\n' + _inspect(key));
}
this.cipher = 'aes' + keyLength;
this[KEY_SYM] = parseKey(key, keyLength / BITS_IN_BYTE);
}
_createClass(SimpleAES, [{
key: 'encrypt',
value: function encrypt(plaintext) {
if (!(typeof plaintext === 'string')) {
throw new TypeError('Value of argument "plaintext" violates contract.\n\nExpected:\nstring\n\nGot:\n' + _inspect(plaintext));
}
var ptBuf = Buffer.from(plaintext, 'utf8');
var ivBuf = _crypto2.default.randomBytes(BLOCK_SIZE);
var cipher = _crypto2.default.createCipheriv(this.cipher, this[KEY_SYM], ivBuf);
var ctBuf = Buffer.concat([cipher.update(ptBuf), cipher.final()]);
return {
iv: ivBuf.toString('base64'),
ciphertext: ctBuf.toString('base64')
};
}
}, {
key: 'decrypt',
value: function decrypt(iv, ciphertext) {
if (!(typeof iv === 'string')) {
throw new TypeError('Value of argument "iv" violates contract.\n\nExpected:\nstring\n\nGot:\n' + _inspect(iv));
}
if (!(typeof ciphertext === 'string')) {
throw new TypeError('Value of argument "ciphertext" violates contract.\n\nExpected:\nstring\n\nGot:\n' + _inspect(ciphertext));
}
var ivBuf = new Buffer(iv, 'base64');
var ctBuf = new Buffer(ciphertext, 'base64');
var decipher = _crypto2.default.createDecipheriv(this.cipher, this[KEY_SYM], ivBuf);
var ptBuf = Buffer.concat([decipher.update(ctBuf), decipher.final()]);
return ptBuf.toString('utf8');
}
}]);
return SimpleAES;
}();
exports.default = SimpleAES;
function parseKey(key, expectedSize) {
if (!(typeof key === 'string' || key instanceof Buffer)) {
throw new TypeError('Value of argument "key" violates contract.\n\nExpected:\nstring | Buffer\n\nGot:\n' + _inspect(key));
}
if (!(typeof expectedSize === 'number')) {
throw new TypeError('Value of argument "expectedSize" violates contract.\n\nExpected:\nnumber\n\nGot:\n' + _inspect(expectedSize));
}
var buf = void 0;
if (key instanceof Buffer) {
buf = key;
} else {
if (!key.match(/^([0-9a-f]{2})+$/i)) throw new Error('invalid_key_hex');
buf = Buffer.from(key, 'hex');
}
if (buf.length !== expectedSize) throw new Error('wrong_key_length');
return buf;
}
function _inspect(input, depth) {
var maxDepth = 4;
var maxKeys = 15;
if (depth === undefined) {
depth = 0;
}
depth += 1;
if (input === null) {
return 'null';
} else if (input === undefined) {
return 'void';
} else if (typeof input === 'string' || typeof input === 'number' || typeof input === 'boolean') {
return typeof input === 'undefined' ? 'undefined' : _typeof(input);
} else if (Array.isArray(input)) {
if (input.length > 0) {
if (depth > maxDepth) return '[...]';
var first = _inspect(input[0], depth);
if (input.every(function (item) {
return _inspect(item, depth) === first;
})) {
return first.trim() + '[]';
} else {
return '[' + input.slice(0, maxKeys).map(function (item) {
return _inspect(item, depth);
}).join(', ') + (input.length >= maxKeys ? ', ...' : '') + ']';
}
} else {
return 'Array';
}
} else {
var keys = Object.keys(input);
if (!keys.length) {
if (input.constructor && input.constructor.name && input.constructor.name !== 'Object') {
return input.constructor.name;
} else {
return 'Object';
}
}
if (depth > maxDepth) return '{...}';
var indent = ' '.repeat(depth - 1);
var entries = keys.slice(0, maxKeys).map(function (key) {
return (/^([A-Z_$][A-Z0-9_$]*)$/i.test(key) ? key : JSON.stringify(key)) + ': ' + _inspect(input[key], depth) + ';';
}).join('\n ' + indent);
if (keys.length >= maxKeys) {
entries += '\n ' + indent + '...';
}
if (input.constructor && input.constructor.name && input.constructor.name !== 'Object') {
return input.constructor.name + ' {\n ' + indent + entries + '\n' + indent + '}';
} else {
return '{\n ' + indent + entries + '\n' + indent + '}';
}
}
}
//# sourceMappingURL=index.js.map