UNPKG

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