json-q
Version:
Retrieves values from JSON objects (and JavaScript objects) by css-selector-like query (includes attribute filters and array flattening).
118 lines (109 loc) • 2.91 kB
JavaScript
var aes = require('./aes');
var Transform = require('./cipherBase');
var inherits = require('inherits');
var modes = require('./modes');
var StreamCipher = require('./streamCipher');
var ebtk = require('./EVP_BytesToKey');
inherits(Decipher, Transform);
function Decipher(mode, key, iv) {
if (!(this instanceof Decipher)) {
return new Decipher(mode, key, iv);
}
Transform.call(this);
this._cache = new Splitter();
this._last = void 0;
this._cipher = new aes.AES(key);
this._prev = new Buffer(iv.length);
iv.copy(this._prev);
this._mode = mode;
}
Decipher.prototype._transform = function (data, _, next) {
this._cache.add(data);
var chunk;
var thing;
while ((chunk = this._cache.get())) {
thing = this._mode.decrypt(this, chunk);
this.push(thing);
}
next();
};
Decipher.prototype._flush = function (next) {
var chunk = this._cache.flush();
if (!chunk) {
return next;
}
this.push(unpad(this._mode.decrypt(this, chunk)));
next();
};
function Splitter() {
if (!(this instanceof Splitter)) {
return new Splitter();
}
this.cache = new Buffer('');
}
Splitter.prototype.add = function (data) {
this.cache = Buffer.concat([this.cache, data]);
};
Splitter.prototype.get = function () {
if (this.cache.length > 16) {
var out = this.cache.slice(0, 16);
this.cache = this.cache.slice(16);
return out;
}
return null;
};
Splitter.prototype.flush = function () {
if (this.cache.length) {
return this.cache;
}
};
function unpad(last) {
var padded = last[15];
if (padded === 16) {
return;
}
return last.slice(0, 16 - padded);
}
var modelist = {
ECB: require('./modes/ecb'),
CBC: require('./modes/cbc'),
CFB: require('./modes/cfb'),
OFB: require('./modes/ofb'),
CTR: require('./modes/ctr')
};
module.exports = function (crypto) {
function createDecipheriv(suite, password, iv) {
var config = modes[suite];
if (!config) {
throw new TypeError('invalid suite type');
}
if (typeof iv === 'string') {
iv = new Buffer(iv);
}
if (typeof password === 'string') {
password = new Buffer(password);
}
if (password.length !== config.key/8) {
throw new TypeError('invalid key length ' + password.length);
}
if (iv.length !== config.iv) {
throw new TypeError('invalid iv length ' + iv.length);
}
if (config.type === 'stream') {
return new StreamCipher(modelist[config.mode], password, iv, true);
}
return new Decipher(modelist[config.mode], password, iv);
}
function createDecipher (suite, password) {
var config = modes[suite];
if (!config) {
throw new TypeError('invalid suite type');
}
var keys = ebtk(crypto, password, config.key, config.iv);
return createDecipheriv(suite, keys.key, keys.iv);
}
return {
createDecipher: createDecipher,
createDecipheriv: createDecipheriv
};
};