UNPKG

2.91 kBJavaScriptView Raw
1var aes = require('./aes');
2var Transform = require('./cipherBase');
3var inherits = require('inherits');
4var modes = require('./modes');
5var StreamCipher = require('./streamCipher');
6var ebtk = require('./EVP_BytesToKey');
7
8inherits(Decipher, Transform);
9function Decipher(mode, key, iv) {
10 if (!(this instanceof Decipher)) {
11 return new Decipher(mode, key, iv);
12 }
13 Transform.call(this);
14 this._cache = new Splitter();
15 this._last = void 0;
16 this._cipher = new aes.AES(key);
17 this._prev = new Buffer(iv.length);
18 iv.copy(this._prev);
19 this._mode = mode;
20}
21Decipher.prototype._transform = function (data, _, next) {
22 this._cache.add(data);
23 var chunk;
24 var thing;
25 while ((chunk = this._cache.get())) {
26 thing = this._mode.decrypt(this, chunk);
27 this.push(thing);
28 }
29 next();
30};
31Decipher.prototype._flush = function (next) {
32 var chunk = this._cache.flush();
33 if (!chunk) {
34 return next;
35 }
36
37 this.push(unpad(this._mode.decrypt(this, chunk)));
38
39 next();
40};
41
42function Splitter() {
43 if (!(this instanceof Splitter)) {
44 return new Splitter();
45 }
46 this.cache = new Buffer('');
47}
48Splitter.prototype.add = function (data) {
49 this.cache = Buffer.concat([this.cache, data]);
50};
51
52Splitter.prototype.get = function () {
53 if (this.cache.length > 16) {
54 var out = this.cache.slice(0, 16);
55 this.cache = this.cache.slice(16);
56 return out;
57 }
58 return null;
59};
60Splitter.prototype.flush = function () {
61 if (this.cache.length) {
62 return this.cache;
63 }
64};
65function unpad(last) {
66 var padded = last[15];
67 if (padded === 16) {
68 return;
69 }
70 return last.slice(0, 16 - padded);
71}
72
73var modelist = {
74 ECB: require('./modes/ecb'),
75 CBC: require('./modes/cbc'),
76 CFB: require('./modes/cfb'),
77 OFB: require('./modes/ofb'),
78 CTR: require('./modes/ctr')
79};
80
81module.exports = function (crypto) {
82 function createDecipheriv(suite, password, iv) {
83 var config = modes[suite];
84 if (!config) {
85 throw new TypeError('invalid suite type');
86 }
87 if (typeof iv === 'string') {
88 iv = new Buffer(iv);
89 }
90 if (typeof password === 'string') {
91 password = new Buffer(password);
92 }
93 if (password.length !== config.key/8) {
94 throw new TypeError('invalid key length ' + password.length);
95 }
96 if (iv.length !== config.iv) {
97 throw new TypeError('invalid iv length ' + iv.length);
98 }
99 if (config.type === 'stream') {
100 return new StreamCipher(modelist[config.mode], password, iv, true);
101 }
102 return new Decipher(modelist[config.mode], password, iv);
103 }
104
105 function createDecipher (suite, password) {
106 var config = modes[suite];
107 if (!config) {
108 throw new TypeError('invalid suite type');
109 }
110 var keys = ebtk(crypto, password, config.key, config.iv);
111 return createDecipheriv(suite, keys.key, keys.iv);
112 }
113 return {
114 createDecipher: createDecipher,
115 createDecipheriv: createDecipheriv
116 };
117};