[Pkg-javascript-commits] [node-browserify-aes] 23/92: truly streaming
Bastien Roucariès
rouca at moszumanska.debian.org
Sun Jun 4 09:35:16 UTC 2017
This is an automated email from the git hooks/post-receive script.
rouca pushed a commit to branch master
in repository node-browserify-aes.
commit ba5f9cc12aa663495f0f93eb5ebc8d5fa395f780
Author: Calvin Metcalf <cmetcalf at appgeo.com>
Date: Tue Oct 28 15:37:37 2014 -0400
truly streaming
---
cipherBase.js | 32 +++++++++++++++++++++++++++++
decrypter.js | 30 +++++----------------------
encrypter.js | 30 +++++----------------------
modes.js | 45 ++++++++++++++++++++++++++--------------
modes/cfb.js | 35 ++++++++++++++++++++++---------
modes/ctr.js | 12 +++++++++--
modes/ofb.js | 12 +++++++++--
streamCipher.js | 26 +++++++++++++++++++++++
test/index.js | 64 +++++++++++++++++++++++++++++++++++++++------------------
9 files changed, 187 insertions(+), 99 deletions(-)
diff --git a/cipherBase.js b/cipherBase.js
new file mode 100644
index 0000000..e580048
--- /dev/null
+++ b/cipherBase.js
@@ -0,0 +1,32 @@
+var Transform = require('stream').Transform;
+var inherits = require('inherits');
+
+module.exports = CipherBase;
+inherits(CipherBase, Transform);
+function CipherBase() {
+ Transform.call(this);
+}
+CipherBase.prototype.update = function (data, inputEnd, outputEnc) {
+ this.write(data, inputEnd);
+ var outData = new Buffer('');
+ var chunk;
+ while ((chunk = this.read())) {
+ outData = Buffer.concat([outData, chunk]);
+ }
+ if (outputEnc) {
+ outData = outData.toString(outputEnc);
+ }
+ return outData;
+};
+CipherBase.prototype.final = function (outputEnc) {
+ this.end();
+ var outData = new Buffer('');
+ var chunk;
+ while ((chunk = this.read())) {
+ outData = Buffer.concat([outData, chunk]);
+ }
+ if (outputEnc) {
+ outData = outData.toString(outputEnc);
+ }
+ return outData;
+};
\ No newline at end of file
diff --git a/decrypter.js b/decrypter.js
index e3888d5..5d840d2 100644
--- a/decrypter.js
+++ b/decrypter.js
@@ -1,7 +1,8 @@
var aes = require('./aes');
-var Transform = require('stream').Transform;
+var Transform = require('./cipherBase');
var inherits = require('inherits');
var modes = require('./modes');
+var StreamCipher = require('./streamCipher');
var ebtk = require('./EVP_BytesToKey');
inherits(Decipher, Transform);
@@ -44,30 +45,6 @@ Decipher.prototype._flush = function (next) {
}
next();
};
-Decipher.prototype.update = function (data, inputEnd, outputEnc) {
- this.write(data, inputEnd);
- var outData = new Buffer('');
- var chunk;
- while ((chunk = this.read())) {
- outData = Buffer.concat([outData, chunk]);
- }
- if (outputEnc) {
- outData = outData.toString(outputEnc);
- }
- return outData;
-};
-Decipher.prototype.final = function (outputEnc) {
- this.end();
- var outData = new Buffer('');
- var chunk;
- while ((chunk = this.read())) {
- outData = Buffer.concat([outData, chunk]);
- }
- if (outputEnc) {
- outData = outData.toString(outputEnc);
- }
- return outData;
-};
function Splitter() {
if (!(this instanceof Splitter)) {
@@ -126,6 +103,9 @@ module.exports = function (crypto) {
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(config.padding, modelist[config.mode], password, iv);
}
diff --git a/encrypter.js b/encrypter.js
index d14ebac..d05fe64 100644
--- a/encrypter.js
+++ b/encrypter.js
@@ -1,8 +1,9 @@
var aes = require('./aes');
-var Transform = require('stream').Transform;
+var Transform = require('./cipherBase');
var inherits = require('inherits');
var modes = require('./modes');
var ebtk = require('./EVP_BytesToKey');
+var StreamCipher = require('./streamCipher');
inherits(Cipher, Transform);
function Cipher(padding, mode, key, iv) {
if (!(this instanceof Cipher)) {
@@ -32,30 +33,6 @@ Cipher.prototype._flush = function (next) {
next();
};
-Cipher.prototype.update = function (data, inputEnd, outputEnc) {
- this.write(data, inputEnd);
- var outData = new Buffer('');
- var chunk;
- while ((chunk = this.read())) {
- outData = Buffer.concat([outData, chunk]);
- }
- if (outputEnc) {
- outData = outData.toString(outputEnc);
- }
- return outData;
-};
-Cipher.prototype.final = function (outputEnc) {
- this.end();
- var outData = new Buffer('');
- var chunk;
- while ((chunk = this.read())) {
- outData = Buffer.concat([outData, chunk]);
- }
- if (outputEnc) {
- outData = outData.toString(outputEnc);
- }
- return outData;
-};
function Splitter(padding) {
if (!(this instanceof Splitter)) {
@@ -119,6 +96,9 @@ module.exports = function (crypto) {
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);
+ }
return new Cipher(config.padding, modelist[config.mode], password, iv);
}
function createCipher (suite, password) {
diff --git a/modes.js b/modes.js
index bef542c..10f6321 100644
--- a/modes.js
+++ b/modes.js
@@ -2,37 +2,43 @@ exports['aes-128-ecb'] = {
cipher: 'AES',
key: 128,
iv: 0,
- mode: 'ECB'
+ mode: 'ECB',
+ type: 'block'
};
exports['aes-192-ecb'] = {
cipher: 'AES',
key: 192,
iv: 0,
- mode: 'ECB'
+ mode: 'ECB',
+ type: 'block'
};
exports['aes-256-ecb'] = {
cipher: 'AES',
key: 256,
iv: 0,
- mode: 'ECB'
+ mode: 'ECB',
+ type: 'block'
};
exports['aes-128-cbc'] = {
cipher: 'AES',
key: 128,
iv: 16,
- mode: 'CBC'
+ mode: 'CBC',
+ type: 'block'
};
exports['aes-192-cbc'] = {
cipher: 'AES',
key: 192,
iv: 16,
- mode: 'CBC'
+ mode: 'CBC',
+ type: 'block'
};
exports['aes-256-cbc'] = {
cipher: 'AES',
key: 256,
iv: 16,
- mode: 'CBC'
+ mode: 'CBC',
+ type: 'block'
};
exports['aes128'] = exports['aes-128-cbc'];
exports['aes192'] = exports['aes-192-cbc'];
@@ -42,61 +48,70 @@ exports['aes-128-cfb'] = {
key: 128,
iv: 16,
mode: 'CFB',
- padding: false
+ padding: false,
+ type: 'stream'
};
exports['aes-192-cfb'] = {
cipher: 'AES',
key: 192,
iv: 16,
mode: 'CFB',
- padding: false
+ padding: false,
+ type: 'stream'
};
exports['aes-256-cfb'] = {
cipher: 'AES',
key: 256,
iv: 16,
mode: 'CFB',
- padding: false
+ padding: false,
+ type: 'stream'
};
exports['aes-128-ofb'] = {
cipher: 'AES',
key: 128,
iv: 16,
mode: 'OFB',
- padding: false
+ padding: false,
+ type: 'stream'
};
exports['aes-192-ofb'] = {
cipher: 'AES',
key: 192,
iv: 16,
mode: 'OFB',
- padding: false
+ padding: false,
+ type: 'stream'
};
exports['aes-256-ofb'] = {
cipher: 'AES',
key: 256,
iv: 16,
mode: 'OFB',
- padding: false
+ padding: false,
+ type: 'stream'
};
exports['aes-128-ctr'] = {
cipher: 'AES',
key: 128,
iv: 16,
mode: 'CTR',
- padding: false
+ padding: false,
+ type: 'stream'
};
exports['aes-192-ctr'] = {
cipher: 'AES',
key: 192,
iv: 16,
mode: 'CTR',
- padding: false
+ padding: false,
+ type: 'stream'
};
exports['aes-256-ctr'] = {
cipher: 'AES',
key: 256,
iv: 16,
mode: 'CTR',
- padding: false
+ padding: false,
+ type: 'stream'
};
\ No newline at end of file
diff --git a/modes/cfb.js b/modes/cfb.js
index 978b637..13712b4 100644
--- a/modes/cfb.js
+++ b/modes/cfb.js
@@ -1,12 +1,27 @@
var xor = require('../xor');
-exports.encrypt = function (self, block) {
- var pad = self._cipher.encryptBlock(self._prev);
- self._prev = xor(block, pad);
- return self._prev;
+exports.encrypt = function (self, data, decrypt) {
+ var out = new Buffer('');
+ var len;
+ while (data.length) {
+ if (self._cache.length === 0) {
+ self._cache = self._cipher.encryptBlock(self._prev);
+ self._prev = new Buffer('');
+ }
+ if (self._cache.length <= data.length) {
+ len = self._cache.length;
+ out = Buffer.concat([out, encryptStart(self, data.slice(0, len), decrypt)]);
+ data = data.slice(len);
+ } else {
+ out = Buffer.concat([out, encryptStart(self, data, decrypt)]);
+ break;
+ }
+ }
+ return out;
};
-exports.decrypt = function (self, block) {
- // yes encrypt
- var pad = self._cipher.encryptBlock(self._prev);
- self._prev = block;
- return xor(pad, block);
-};
\ No newline at end of file
+function encryptStart(self, data, decrypt) {
+ var len = data.length;
+ var out = xor(data, self._cache);
+ self._cache = self._cache.slice(len);
+ self._prev = Buffer.concat([self._prev, decrypt?data:out]);
+ return out;
+}
\ No newline at end of file
diff --git a/modes/ctr.js b/modes/ctr.js
index cbf3fe0..b345b0e 100644
--- a/modes/ctr.js
+++ b/modes/ctr.js
@@ -1,8 +1,16 @@
var xor = require('../xor');
-exports.encrypt = exports.decrypt = function (self, block) {
- var out = xor(block, self._cipher.encryptBlock(self._prev));
+function getBlock(self) {
+ var out = self._cipher.encryptBlock(self._prev);
incr32(self._prev);
return out;
+}
+exports.encrypt = function (self, chunk) {
+ while (self._cache.length < chunk.length) {
+ self._cache = Buffer.concat([self._cache, getBlock(self)]);
+ }
+ var pad = self._cache.slice(0, chunk.length);
+ self._cache = self._cache.slice(chunk.length);
+ return xor(chunk, pad);
};
function incr32(iv) {
var len = iv.length;
diff --git a/modes/ofb.js b/modes/ofb.js
index 49d49b2..43efc5a 100644
--- a/modes/ofb.js
+++ b/modes/ofb.js
@@ -1,5 +1,13 @@
var xor = require('../xor');
-exports.encrypt = exports.decrypt = function (self, block) {
+function getBlock(self) {
self._prev = self._cipher.encryptBlock(self._prev);
- return xor(block, self._prev);
+ return self._prev;
+}
+exports.encrypt = function (self, chunk) {
+ while (self._cache.length < chunk.length) {
+ self._cache = Buffer.concat([self._cache, getBlock(self)]);
+ }
+ var pad = self._cache.slice(0, chunk.length);
+ self._cache = self._cache.slice(chunk.length);
+ return xor(chunk, pad);
};
\ No newline at end of file
diff --git a/streamCipher.js b/streamCipher.js
new file mode 100644
index 0000000..1c5c9c5
--- /dev/null
+++ b/streamCipher.js
@@ -0,0 +1,26 @@
+var aes = require('./aes');
+var Transform = require('./cipherBase');
+var inherits = require('inherits');
+
+inherits(StreamCipher, Transform);
+module.exports = StreamCipher;
+function StreamCipher(mode, key, iv, decrypt) {
+ if (!(this instanceof StreamCipher)) {
+ return new StreamCipher(mode, key, iv);
+ }
+ Transform.call(this);
+ this._cipher = new aes.AES(key);
+ this._prev = new Buffer(iv.length);
+ this._cache = new Buffer('');
+ this._secCache = new Buffer('');
+ this._decrypt = decrypt;
+ iv.copy(this._prev);
+ this._mode = mode;
+}
+StreamCipher.prototype._transform = function (chunk, _, next) {
+ next(null, this._mode.encrypt(this, chunk, this._decrypt));
+};
+StreamCipher.prototype._flush = function (next) {
+ this._cipher.scrub();
+ next();
+};
\ No newline at end of file
diff --git a/test/index.js b/test/index.js
index 26be14f..85fac24 100644
--- a/test/index.js
+++ b/test/index.js
@@ -44,16 +44,22 @@ fixtures.forEach(function (fixture, i) {
suite.end();
});
test('fixture ' + i + ' ' + cipher + '-legacy', function (t) {
- t.plan(1);
+ t.plan(3);
var suite = crypto.createCipher(cipher, new Buffer(fixture.password));
var buf = new Buffer('');
- buf = Buffer.concat([buf, suite.update(new Buffer(fixture.text))]);
- buf = Buffer.concat([buf, suite.final()]);
var suite2 = _crypto.createCipher(cipher, new Buffer(fixture.password));
var buf2 = new Buffer('');
- buf2 = Buffer.concat([buf2, suite2.update(new Buffer(fixture.text))]);
+ var inbuf = new Buffer(fixture.text);
+ var mid = ~~inbuf.length;
+ buf = Buffer.concat([buf, suite.update(inbuf.slice(0, mid))]);
+ buf2 = Buffer.concat([buf2, suite2.update(inbuf.slice(0, mid))]);
+ t.equals(buf.toString('hex'), buf2.toString('hex'), 'intermediate');
+ buf = Buffer.concat([buf, suite.update(inbuf.slice(mid))]);
+ buf2 = Buffer.concat([buf2, suite2.update(inbuf.slice(mid))]);
+ t.equals(buf.toString('hex'), buf2.toString('hex'), 'intermediate 2');
+ buf = Buffer.concat([buf, suite.final()]);
buf2 = Buffer.concat([buf2, suite2.final()]);
- t.equals(buf.toString('hex'), buf2.toString('hex'));
+ t.equals(buf.toString('hex'), buf2.toString('hex'), 'final');
});
test('fixture ' + i + ' ' + cipher + '-decrypt', function (t) {
t.plan(1);
@@ -75,17 +81,23 @@ fixtures.forEach(function (fixture, i) {
suite.end();
});
test('fixture ' + i + ' ' + cipher + '-decrypt-legacy', function (t) {
- t.plan(2);
+ t.plan(4);
var suite = crypto.createDecipher(cipher, new Buffer(fixture.password));
var buf = new Buffer('');
- buf = Buffer.concat([buf, suite.update(new Buffer(fixture.results.ciphers[cipher], 'hex'))]);
- buf = Buffer.concat([buf, suite.final()]);
var suite2 = _crypto.createDecipher(cipher, new Buffer(fixture.password));
var buf2 = new Buffer('');
- buf2 = Buffer.concat([buf2, suite2.update(new Buffer(fixture.results.ciphers[cipher], 'hex'))]);
+ var inbuf = new Buffer(fixture.results.ciphers[cipher], 'hex');
+ var mid = ~~inbuf.length;
+ buf = Buffer.concat([buf, suite.update(inbuf.slice(0, mid))]);
+ buf2 = Buffer.concat([buf2, suite2.update(inbuf.slice(0, mid))]);
+ t.equals(buf.toString('utf8'), buf2.toString('utf8'), 'intermediate');
+ buf = Buffer.concat([buf, suite.update(inbuf.slice(mid))]);
+ buf2 = Buffer.concat([buf2, suite2.update(inbuf.slice(mid))]);
+ t.equals(buf.toString('utf8'), buf2.toString('utf8'), 'intermediate 2');
+ buf = Buffer.concat([buf, suite.final()]);
buf2 = Buffer.concat([buf2, suite2.final()]);
t.equals(buf.toString('utf8'), fixture.text);
- t.equals(buf.toString('utf8'), buf2.toString('utf8'));
+ t.equals(buf.toString('utf8'), buf2.toString('utf8'), 'final');
});
//var cipherivs = fixture.results.cipherivs = {};
types.forEach(function (cipher) {
@@ -109,17 +121,23 @@ fixtures.forEach(function (fixture, i) {
suite.end();
});
test('fixture ' + i + ' ' + cipher + '-legacy-iv', function (t) {
- t.plan(2);
+ t.plan(4);
var suite = crypto.createCipheriv(cipher, ebtk(_crypto, fixture.password, modes[cipher].key).key, new Buffer(fixture.iv, 'hex'));
var buf = new Buffer('');
- buf = Buffer.concat([buf, suite.update(new Buffer(fixture.text))]);
- buf = Buffer.concat([buf, suite.final()]);
var suite2 = _crypto.createCipheriv(cipher, ebtk(_crypto, fixture.password, modes[cipher].key).key, new Buffer(fixture.iv, 'hex'));
var buf2 = new Buffer('');
- buf2 = Buffer.concat([buf2, suite2.update(new Buffer(fixture.text))]);
+ var inbuf = new Buffer(fixture.text);
+ var mid = ~~inbuf.length;
+ buf = Buffer.concat([buf, suite.update(inbuf.slice(0, mid))]);
+ buf2 = Buffer.concat([buf2, suite2.update(inbuf.slice(0, mid))]);
+ t.equals(buf.toString('hex'), buf2.toString('hex'), 'intermediate');
+ buf = Buffer.concat([buf, suite.update(inbuf.slice(mid))]);
+ buf2 = Buffer.concat([buf2, suite2.update(inbuf.slice(mid))]);
+ t.equals(buf.toString('hex'), buf2.toString('hex'), 'intermediate 2');
+ buf = Buffer.concat([buf, suite.final()]);
buf2 = Buffer.concat([buf2, suite2.final()]);
t.equals(buf.toString('hex'), fixture.results.cipherivs[cipher]);
- t.equals(buf.toString('hex'), buf2.toString('hex'));
+ t.equals(buf.toString('hex'), buf2.toString('hex'), 'final');
});
test('fixture ' + i + ' ' + cipher + '-iv-decrypt', function (t) {
t.plan(1);
@@ -138,17 +156,23 @@ fixtures.forEach(function (fixture, i) {
suite.end();
});
test('fixture ' + i + ' ' + cipher + '-decrypt-legacy', function (t) {
- t.plan(2);
+ t.plan(4);
var suite = crypto.createDecipheriv(cipher, ebtk(_crypto, fixture.password, modes[cipher].key).key, new Buffer(fixture.iv, 'hex'));
var buf = new Buffer('');
- buf = Buffer.concat([buf, suite.update(new Buffer(fixture.results.cipherivs[cipher], 'hex'))]);
- buf = Buffer.concat([buf, suite.final()]);
var suite2 = _crypto.createDecipheriv(cipher, ebtk(_crypto, fixture.password, modes[cipher].key).key, new Buffer(fixture.iv, 'hex'));
var buf2 = new Buffer('');
- buf2 = Buffer.concat([buf2, suite2.update(new Buffer(fixture.results.cipherivs[cipher], 'hex'))]);
+ var inbuf = new Buffer(fixture.results.cipherivs[cipher], 'hex');
+ var mid = ~~inbuf.length;
+ buf = Buffer.concat([buf, suite.update(inbuf.slice(0, mid))]);
+ buf2 = Buffer.concat([buf2, suite2.update(inbuf.slice(0, mid))]);
+ t.equals(buf.toString('utf8'), buf2.toString('utf8'), 'intermediate');
+ buf = Buffer.concat([buf, suite.update(inbuf.slice(mid))]);
+ buf2 = Buffer.concat([buf2, suite2.update(inbuf.slice(mid))]);
+ t.equals(buf.toString('utf8'), buf2.toString('utf8'), 'intermediate 2');
+ buf = Buffer.concat([buf, suite.final()]);
buf2 = Buffer.concat([buf2, suite2.final()]);
t.equals(buf.toString('utf8'), fixture.text);
- t.equals(buf.toString('utf8'), buf2.toString('utf8'));
+ t.equals(buf.toString('utf8'), buf2.toString('utf8'), 'final');
});
});
});
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-browserify-aes.git
More information about the Pkg-javascript-commits
mailing list