UNPKG

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