browserify-aes
Advanced tools
Comparing version 1.0.6 to 1.0.7
297
aes.js
// based on the aes implimentation in triple sec | ||
// https://github.com/keybase/triplesec | ||
// which is in turn based on the one from crypto-js | ||
// https://code.google.com/p/crypto-js/ | ||
var uint_max = Math.pow(2, 32) | ||
function fixup_uint32 (x) { | ||
var ret, x_pos | ||
ret = x > uint_max || x < 0 ? (x_pos = Math.abs(x) % uint_max, x < 0 ? uint_max - x_pos : x_pos) : x | ||
return ret | ||
var Buffer = require('safe-buffer').Buffer | ||
function asUInt32Array (buf) { | ||
if (!Buffer.isBuffer(buf)) buf = Buffer.from(buf) | ||
var len = (buf.length / 4) | 0 | ||
var out = new Array(len) | ||
for (var i = 0; i < len; i++) { | ||
out[i] = buf.readUInt32BE(i * 4) | ||
} | ||
return out | ||
} | ||
function scrub_vec (v) { | ||
function scrubVec (v) { | ||
for (var i = 0; i < v.length; v++) { | ||
v[i] = 0 | ||
} | ||
return false | ||
} | ||
function Global () { | ||
this.SBOX = [] | ||
this.INV_SBOX = [] | ||
this.SUB_MIX = [[], [], [], []] | ||
this.INV_SUB_MIX = [[], [], [], []] | ||
this.init() | ||
this.RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36] | ||
function cryptBlock (M, keySchedule, SUB_MIX, SBOX, nRounds) { | ||
var SUB_MIX0 = SUB_MIX[0] | ||
var SUB_MIX1 = SUB_MIX[1] | ||
var SUB_MIX2 = SUB_MIX[2] | ||
var SUB_MIX3 = SUB_MIX[3] | ||
var s0 = M[0] ^ keySchedule[0] | ||
var s1 = M[1] ^ keySchedule[1] | ||
var s2 = M[2] ^ keySchedule[2] | ||
var s3 = M[3] ^ keySchedule[3] | ||
var t0, t1, t2, t3 | ||
var ksRow = 4 | ||
for (var round = 1; round < nRounds; round++) { | ||
t0 = SUB_MIX0[s0 >>> 24] ^ SUB_MIX1[(s1 >>> 16) & 0xff] ^ SUB_MIX2[(s2 >>> 8) & 0xff] ^ SUB_MIX3[s3 & 0xff] ^ keySchedule[ksRow++] | ||
t1 = SUB_MIX0[s1 >>> 24] ^ SUB_MIX1[(s2 >>> 16) & 0xff] ^ SUB_MIX2[(s3 >>> 8) & 0xff] ^ SUB_MIX3[s0 & 0xff] ^ keySchedule[ksRow++] | ||
t2 = SUB_MIX0[s2 >>> 24] ^ SUB_MIX1[(s3 >>> 16) & 0xff] ^ SUB_MIX2[(s0 >>> 8) & 0xff] ^ SUB_MIX3[s1 & 0xff] ^ keySchedule[ksRow++] | ||
t3 = SUB_MIX0[s3 >>> 24] ^ SUB_MIX1[(s0 >>> 16) & 0xff] ^ SUB_MIX2[(s1 >>> 8) & 0xff] ^ SUB_MIX3[s2 & 0xff] ^ keySchedule[ksRow++] | ||
s0 = t0 | ||
s1 = t1 | ||
s2 = t2 | ||
s3 = t3 | ||
} | ||
t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++] | ||
t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++] | ||
t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++] | ||
t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++] | ||
t0 = t0 >>> 0 | ||
t1 = t1 >>> 0 | ||
t2 = t2 >>> 0 | ||
t3 = t3 >>> 0 | ||
return [t0, t1, t2, t3] | ||
} | ||
Global.prototype.init = function () { | ||
var d, i, sx, t, x, x2, x4, x8, xi, _i | ||
d = (function () { | ||
var _i, _results | ||
_results = [] | ||
for (i = _i = 0; _i < 256; i = ++_i) { | ||
if (i < 128) { | ||
_results.push(i << 1) | ||
} else { | ||
_results.push((i << 1) ^ 0x11b) | ||
} | ||
// AES constants | ||
var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36] | ||
var G = (function () { | ||
// Compute double table | ||
var d = new Array(256) | ||
for (var j = 0; j < 256; j++) { | ||
if (j < 128) { | ||
d[j] = j << 1 | ||
} else { | ||
d[j] = (j << 1) ^ 0x11b | ||
} | ||
return _results | ||
})() | ||
x = 0 | ||
xi = 0 | ||
for (i = _i = 0; _i < 256; i = ++_i) { | ||
sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4) | ||
} | ||
var SBOX = [] | ||
var INV_SBOX = [] | ||
var SUB_MIX = [[], [], [], []] | ||
var INV_SUB_MIX = [[], [], [], []] | ||
// Walk GF(2^8) | ||
var x = 0 | ||
var xi = 0 | ||
for (var i = 0; i < 256; ++i) { | ||
// Compute sbox | ||
var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4) | ||
sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63 | ||
this.SBOX[x] = sx | ||
this.INV_SBOX[sx] = x | ||
x2 = d[x] | ||
x4 = d[x2] | ||
x8 = d[x4] | ||
t = (d[sx] * 0x101) ^ (sx * 0x1010100) | ||
this.SUB_MIX[0][x] = (t << 24) | (t >>> 8) | ||
this.SUB_MIX[1][x] = (t << 16) | (t >>> 16) | ||
this.SUB_MIX[2][x] = (t << 8) | (t >>> 24) | ||
this.SUB_MIX[3][x] = t | ||
SBOX[x] = sx | ||
INV_SBOX[sx] = x | ||
// Compute multiplication | ||
var x2 = d[x] | ||
var x4 = d[x2] | ||
var x8 = d[x4] | ||
// Compute sub bytes, mix columns tables | ||
var t = (d[sx] * 0x101) ^ (sx * 0x1010100) | ||
SUB_MIX[0][x] = (t << 24) | (t >>> 8) | ||
SUB_MIX[1][x] = (t << 16) | (t >>> 16) | ||
SUB_MIX[2][x] = (t << 8) | (t >>> 24) | ||
SUB_MIX[3][x] = t | ||
// Compute inv sub bytes, inv mix columns tables | ||
t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100) | ||
this.INV_SUB_MIX[0][sx] = (t << 24) | (t >>> 8) | ||
this.INV_SUB_MIX[1][sx] = (t << 16) | (t >>> 16) | ||
this.INV_SUB_MIX[2][sx] = (t << 8) | (t >>> 24) | ||
this.INV_SUB_MIX[3][sx] = t | ||
INV_SUB_MIX[0][sx] = (t << 24) | (t >>> 8) | ||
INV_SUB_MIX[1][sx] = (t << 16) | (t >>> 16) | ||
INV_SUB_MIX[2][sx] = (t << 8) | (t >>> 24) | ||
INV_SUB_MIX[3][sx] = t | ||
if (x === 0) { | ||
@@ -70,52 +117,83 @@ x = xi = 1 | ||
} | ||
return true | ||
return { | ||
SBOX: SBOX, | ||
INV_SBOX: INV_SBOX, | ||
SUB_MIX: SUB_MIX, | ||
INV_SUB_MIX: INV_SUB_MIX | ||
} | ||
})() | ||
function AES (key) { | ||
this._key = asUInt32Array(key) | ||
this._reset() | ||
} | ||
var G = new Global() | ||
AES.blockSize = 4 * 4 | ||
AES.keySize = 256 / 8 | ||
AES.prototype.blockSize = AES.blockSize | ||
AES.prototype.keySize = AES.keySize | ||
AES.prototype._reset = function () { | ||
var keyWords = this._key | ||
var keySize = keyWords.length | ||
var nRounds = keySize + 6 | ||
var ksRows = (nRounds + 1) * 4 | ||
AES.keySize = 256 / 8 | ||
var keySchedule = [] | ||
for (var k = 0; k < keySize; k++) { | ||
keySchedule[k] = keyWords[k] | ||
} | ||
AES.prototype.keySize = AES.keySize | ||
for (k = keySize; k < ksRows; k++) { | ||
var t = keySchedule[k - 1] | ||
function bufferToArray (buf) { | ||
var len = buf.length / 4 | ||
var out = new Array(len) | ||
var i = -1 | ||
while (++i < len) { | ||
out[i] = buf.readUInt32BE(i * 4) | ||
if (k % keySize === 0) { | ||
t = (t << 8) | (t >>> 24) | ||
t = | ||
(G.SBOX[t >>> 24] << 24) | | ||
(G.SBOX[(t >>> 16) & 0xff] << 16) | | ||
(G.SBOX[(t >>> 8) & 0xff] << 8) | | ||
(G.SBOX[t & 0xff]) | ||
t ^= RCON[(k / keySize) | 0] << 24 | ||
} else if (keySize > 6 && k % keySize === 4) { | ||
t = | ||
(G.SBOX[t >>> 24] << 24) | | ||
(G.SBOX[(t >>> 16) & 0xff] << 16) | | ||
(G.SBOX[(t >>> 8) & 0xff] << 8) | | ||
(G.SBOX[t & 0xff]) | ||
} | ||
keySchedule[k] = keySchedule[k - keySize] ^ t | ||
} | ||
return out | ||
} | ||
function AES (key) { | ||
this._key = bufferToArray(key) | ||
this._doReset() | ||
} | ||
AES.prototype._doReset = function () { | ||
var invKsRow, keySize, keyWords, ksRow, ksRows, t | ||
keyWords = this._key | ||
keySize = keyWords.length | ||
this._nRounds = keySize + 6 | ||
ksRows = (this._nRounds + 1) * 4 | ||
this._keySchedule = [] | ||
for (ksRow = 0; ksRow < ksRows; ksRow++) { | ||
this._keySchedule[ksRow] = ksRow < keySize ? keyWords[ksRow] : (t = this._keySchedule[ksRow - 1], (ksRow % keySize) === 0 ? (t = (t << 8) | (t >>> 24), t = (G.SBOX[t >>> 24] << 24) | (G.SBOX[(t >>> 16) & 0xff] << 16) | (G.SBOX[(t >>> 8) & 0xff] << 8) | G.SBOX[t & 0xff], t ^= G.RCON[(ksRow / keySize) | 0] << 24) : keySize > 6 && ksRow % keySize === 4 ? t = (G.SBOX[t >>> 24] << 24) | (G.SBOX[(t >>> 16) & 0xff] << 16) | (G.SBOX[(t >>> 8) & 0xff] << 8) | G.SBOX[t & 0xff] : void 0, this._keySchedule[ksRow - keySize] ^ t) | ||
var invKeySchedule = [] | ||
for (var ik = 0; ik < ksRows; ik++) { | ||
var ksR = ksRows - ik | ||
var tt = keySchedule[ksR - (ik % 4 ? 0 : 4)] | ||
if (ik < 4 || ksR <= 4) { | ||
invKeySchedule[ik] = tt | ||
} else { | ||
invKeySchedule[ik] = | ||
G.INV_SUB_MIX[0][G.SBOX[tt >>> 24]] ^ | ||
G.INV_SUB_MIX[1][G.SBOX[(tt >>> 16) & 0xff]] ^ | ||
G.INV_SUB_MIX[2][G.SBOX[(tt >>> 8) & 0xff]] ^ | ||
G.INV_SUB_MIX[3][G.SBOX[tt & 0xff]] | ||
} | ||
} | ||
this._invKeySchedule = [] | ||
for (invKsRow = 0; invKsRow < ksRows; invKsRow++) { | ||
ksRow = ksRows - invKsRow | ||
t = this._keySchedule[ksRow - (invKsRow % 4 ? 0 : 4)] | ||
this._invKeySchedule[invKsRow] = invKsRow < 4 || ksRow <= 4 ? t : G.INV_SUB_MIX[0][G.SBOX[t >>> 24]] ^ G.INV_SUB_MIX[1][G.SBOX[(t >>> 16) & 0xff]] ^ G.INV_SUB_MIX[2][G.SBOX[(t >>> 8) & 0xff]] ^ G.INV_SUB_MIX[3][G.SBOX[t & 0xff]] | ||
} | ||
return true | ||
this._nRounds = nRounds | ||
this._keySchedule = keySchedule | ||
this._invKeySchedule = invKeySchedule | ||
} | ||
AES.prototype.encryptBlockRaw = function (M) { | ||
M = asUInt32Array(M) | ||
return cryptBlock(M, this._keySchedule, G.SUB_MIX, G.SBOX, this._nRounds) | ||
} | ||
AES.prototype.encryptBlock = function (M) { | ||
M = bufferToArray(new Buffer(M)) | ||
var out = this._doCryptBlock(M, this._keySchedule, G.SUB_MIX, G.SBOX) | ||
var buf = new Buffer(16) | ||
var out = this.encryptBlockRaw(M) | ||
var buf = Buffer.allocUnsafe(16) | ||
buf.writeUInt32BE(out[0], 0) | ||
@@ -129,8 +207,11 @@ buf.writeUInt32BE(out[1], 4) | ||
AES.prototype.decryptBlock = function (M) { | ||
M = bufferToArray(new Buffer(M)) | ||
var temp = [M[3], M[1]] | ||
M[1] = temp[0] | ||
M[3] = temp[1] | ||
var out = this._doCryptBlock(M, this._invKeySchedule, G.INV_SUB_MIX, G.INV_SBOX) | ||
var buf = new Buffer(16) | ||
M = asUInt32Array(M) | ||
// swap | ||
var m1 = M[1] | ||
M[1] = M[3] | ||
M[3] = m1 | ||
var out = cryptBlock(M, this._invKeySchedule, G.INV_SUB_MIX, G.INV_SBOX, this._nRounds) | ||
var buf = Buffer.allocUnsafe(16) | ||
buf.writeUInt32BE(out[0], 0) | ||
@@ -144,37 +225,7 @@ buf.writeUInt32BE(out[3], 4) | ||
AES.prototype.scrub = function () { | ||
scrub_vec(this._keySchedule) | ||
scrub_vec(this._invKeySchedule) | ||
scrub_vec(this._key) | ||
scrubVec(this._keySchedule) | ||
scrubVec(this._invKeySchedule) | ||
scrubVec(this._key) | ||
} | ||
AES.prototype._doCryptBlock = function (M, keySchedule, SUB_MIX, SBOX) { | ||
var ksRow, s0, s1, s2, s3, t0, t1, t2, t3 | ||
s0 = M[0] ^ keySchedule[0] | ||
s1 = M[1] ^ keySchedule[1] | ||
s2 = M[2] ^ keySchedule[2] | ||
s3 = M[3] ^ keySchedule[3] | ||
ksRow = 4 | ||
for (var round = 1; round < this._nRounds; round++) { | ||
t0 = SUB_MIX[0][s0 >>> 24] ^ SUB_MIX[1][(s1 >>> 16) & 0xff] ^ SUB_MIX[2][(s2 >>> 8) & 0xff] ^ SUB_MIX[3][s3 & 0xff] ^ keySchedule[ksRow++] | ||
t1 = SUB_MIX[0][s1 >>> 24] ^ SUB_MIX[1][(s2 >>> 16) & 0xff] ^ SUB_MIX[2][(s3 >>> 8) & 0xff] ^ SUB_MIX[3][s0 & 0xff] ^ keySchedule[ksRow++] | ||
t2 = SUB_MIX[0][s2 >>> 24] ^ SUB_MIX[1][(s3 >>> 16) & 0xff] ^ SUB_MIX[2][(s0 >>> 8) & 0xff] ^ SUB_MIX[3][s1 & 0xff] ^ keySchedule[ksRow++] | ||
t3 = SUB_MIX[0][s3 >>> 24] ^ SUB_MIX[1][(s0 >>> 16) & 0xff] ^ SUB_MIX[2][(s1 >>> 8) & 0xff] ^ SUB_MIX[3][s2 & 0xff] ^ keySchedule[ksRow++] | ||
s0 = t0 | ||
s1 = t1 | ||
s2 = t2 | ||
s3 = t3 | ||
} | ||
t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++] | ||
t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++] | ||
t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++] | ||
t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++] | ||
return [ | ||
fixup_uint32(t0), | ||
fixup_uint32(t1), | ||
fixup_uint32(t2), | ||
fixup_uint32(t3) | ||
] | ||
} | ||
exports.AES = AES | ||
module.exports.AES = AES |
var aes = require('./aes') | ||
var Buffer = require('safe-buffer').Buffer | ||
var Transform = require('cipher-base') | ||
@@ -6,23 +7,31 @@ var inherits = require('inherits') | ||
var xor = require('buffer-xor') | ||
inherits(StreamCipher, Transform) | ||
module.exports = StreamCipher | ||
function xorTest (a, b) { | ||
var out = 0 | ||
if (a.length !== b.length) out++ | ||
var len = Math.min(a.length, b.length) | ||
for (var i = 0; i < len; ++i) { | ||
out += (a[i] ^ b[i]) | ||
} | ||
return out | ||
} | ||
function StreamCipher (mode, key, iv, decrypt) { | ||
if (!(this instanceof StreamCipher)) { | ||
return new StreamCipher(mode, key, iv) | ||
} | ||
Transform.call(this) | ||
this._finID = Buffer.concat([iv, new Buffer([0, 0, 0, 1])]) | ||
iv = Buffer.concat([iv, new Buffer([0, 0, 0, 2])]) | ||
this._finID = Buffer.concat([iv, Buffer.from([0, 0, 0, 1])]) | ||
iv = Buffer.concat([iv, Buffer.from([0, 0, 0, 2])]) | ||
this._cipher = new aes.AES(key) | ||
this._prev = new Buffer(iv.length) | ||
this._cache = new Buffer('') | ||
this._secCache = new Buffer('') | ||
this._prev = Buffer.from(iv) | ||
this._cache = Buffer.allocUnsafe(0) | ||
this._secCache = Buffer.allocUnsafe(0) | ||
this._decrypt = decrypt | ||
this._alen = 0 | ||
this._len = 0 | ||
iv.copy(this._prev) | ||
this._mode = mode | ||
var h = new Buffer(4) | ||
h.fill(0) | ||
var h = Buffer.alloc(4, 0) | ||
this._ghash = new GHASH(this._cipher.encryptBlock(h)) | ||
@@ -32,2 +41,5 @@ this._authTag = null | ||
} | ||
inherits(StreamCipher, Transform) | ||
StreamCipher.prototype._update = function (chunk) { | ||
@@ -37,7 +49,7 @@ if (!this._called && this._alen) { | ||
if (rump < 16) { | ||
rump = new Buffer(rump) | ||
rump.fill(0) | ||
rump = Buffer.alloc(rump, 0) | ||
this._ghash.update(rump) | ||
} | ||
} | ||
this._called = true | ||
@@ -53,49 +65,32 @@ var out = this._mode.encrypt(this, chunk) | ||
} | ||
StreamCipher.prototype._final = function () { | ||
if (this._decrypt && !this._authTag) { | ||
throw new Error('Unsupported state or unable to authenticate data') | ||
} | ||
if (this._decrypt && !this._authTag) throw new Error('Unsupported state or unable to authenticate data') | ||
var tag = xor(this._ghash.final(this._alen * 8, this._len * 8), this._cipher.encryptBlock(this._finID)) | ||
if (this._decrypt) { | ||
if (xorTest(tag, this._authTag)) { | ||
throw new Error('Unsupported state or unable to authenticate data') | ||
} | ||
} else { | ||
this._authTag = tag | ||
} | ||
if (this._decrypt && xorTest(tag, this._authTag)) throw new Error('Unsupported state or unable to authenticate data') | ||
this._authTag = tag | ||
this._cipher.scrub() | ||
} | ||
StreamCipher.prototype.getAuthTag = function getAuthTag () { | ||
if (!this._decrypt && Buffer.isBuffer(this._authTag)) { | ||
return this._authTag | ||
} else { | ||
throw new Error('Attempting to get auth tag in unsupported state') | ||
} | ||
if (this._decrypt || !Buffer.isBuffer(this._authTag)) throw new Error('Attempting to get auth tag in unsupported state') | ||
return this._authTag | ||
} | ||
StreamCipher.prototype.setAuthTag = function setAuthTag (tag) { | ||
if (this._decrypt) { | ||
this._authTag = tag | ||
} else { | ||
throw new Error('Attempting to set auth tag in unsupported state') | ||
} | ||
if (!this._decrypt) throw new Error('Attempting to set auth tag in unsupported state') | ||
this._authTag = tag | ||
} | ||
StreamCipher.prototype.setAAD = function setAAD (buf) { | ||
if (!this._called) { | ||
this._ghash.update(buf) | ||
this._alen += buf.length | ||
} else { | ||
throw new Error('Attempting to set AAD in unsupported state') | ||
} | ||
if (this._called) throw new Error('Attempting to set AAD in unsupported state') | ||
this._ghash.update(buf) | ||
this._alen += buf.length | ||
} | ||
function xorTest (a, b) { | ||
var out = 0 | ||
if (a.length !== b.length) { | ||
out++ | ||
} | ||
var len = Math.min(a.length, b.length) | ||
var i = -1 | ||
while (++i < len) { | ||
out += (a[i] ^ b[i]) | ||
} | ||
return out | ||
} | ||
module.exports = StreamCipher |
var ciphers = require('./encrypter') | ||
var deciphers = require('./decrypter') | ||
var modes = require('./modes/list.json') | ||
function getCiphers () { | ||
return Object.keys(modes) | ||
} | ||
exports.createCipher = exports.Cipher = ciphers.createCipher | ||
exports.createCipheriv = exports.Cipheriv = ciphers.createCipheriv | ||
var deciphers = require('./decrypter') | ||
exports.createDecipher = exports.Decipher = deciphers.createDecipher | ||
exports.createDecipheriv = exports.Decipheriv = deciphers.createDecipheriv | ||
var modes = require('./modes') | ||
function getCiphers () { | ||
return Object.keys(modes) | ||
} | ||
exports.listCiphers = exports.getCiphers = getCiphers |
@@ -0,23 +1,23 @@ | ||
var AuthCipher = require('./authCipher') | ||
var Buffer = require('safe-buffer').Buffer | ||
var MODES = require('./modes') | ||
var StreamCipher = require('./streamCipher') | ||
var Transform = require('cipher-base') | ||
var aes = require('./aes') | ||
var Transform = require('cipher-base') | ||
var ebtk = require('evp_bytestokey') | ||
var inherits = require('inherits') | ||
var modes = require('./modes') | ||
var StreamCipher = require('./streamCipher') | ||
var AuthCipher = require('./authCipher') | ||
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._prev = Buffer.from(iv) | ||
this._mode = mode | ||
this._autopadding = true | ||
} | ||
inherits(Decipher, Transform) | ||
Decipher.prototype._update = function (data) { | ||
@@ -34,2 +34,3 @@ this._cache.add(data) | ||
} | ||
Decipher.prototype._final = function () { | ||
@@ -43,2 +44,3 @@ var chunk = this._cache.flush() | ||
} | ||
Decipher.prototype.setAutoPadding = function (setTo) { | ||
@@ -48,8 +50,7 @@ this._autopadding = !!setTo | ||
} | ||
function Splitter () { | ||
if (!(this instanceof Splitter)) { | ||
return new Splitter() | ||
} | ||
this.cache = new Buffer('') | ||
this.cache = Buffer.allocUnsafe(0) | ||
} | ||
Splitter.prototype.add = function (data) { | ||
@@ -74,9 +75,10 @@ this.cache = Buffer.concat([this.cache, data]) | ||
} | ||
return null | ||
} | ||
Splitter.prototype.flush = function () { | ||
if (this.cache.length) { | ||
return this.cache | ||
} | ||
if (this.cache.length) return this.cache | ||
} | ||
function unpad (last) { | ||
@@ -90,53 +92,35 @@ var padded = last[15] | ||
} | ||
if (padded === 16) { | ||
return | ||
} | ||
if (padded === 16) return | ||
return last.slice(0, 16 - padded) | ||
} | ||
var modelist = { | ||
ECB: require('./modes/ecb'), | ||
CBC: require('./modes/cbc'), | ||
CFB: require('./modes/cfb'), | ||
CFB8: require('./modes/cfb8'), | ||
CFB1: require('./modes/cfb1'), | ||
OFB: require('./modes/ofb'), | ||
CTR: require('./modes/ctr'), | ||
GCM: require('./modes/ctr') | ||
} | ||
function createDecipheriv (suite, password, iv) { | ||
var config = MODES[suite.toLowerCase()] | ||
if (!config) throw new TypeError('invalid suite type') | ||
function createDecipheriv (suite, password, iv) { | ||
var config = modes[suite.toLowerCase()] | ||
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 (typeof iv === 'string') iv = Buffer.from(iv) | ||
if (iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length) | ||
if (typeof password === 'string') password = Buffer.from(password) | ||
if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length) | ||
if (config.type === 'stream') { | ||
return new StreamCipher(modelist[config.mode], password, iv, true) | ||
return new StreamCipher(config.module, password, iv, true) | ||
} else if (config.type === 'auth') { | ||
return new AuthCipher(modelist[config.mode], password, iv, true) | ||
return new AuthCipher(config.module, password, iv, true) | ||
} | ||
return new Decipher(modelist[config.mode], password, iv) | ||
return new Decipher(config.module, password, iv) | ||
} | ||
function createDecipher (suite, password) { | ||
var config = modes[suite.toLowerCase()] | ||
if (!config) { | ||
throw new TypeError('invalid suite type') | ||
} | ||
var config = MODES[suite.toLowerCase()] | ||
if (!config) throw new TypeError('invalid suite type') | ||
var keys = ebtk(password, false, config.key, config.iv) | ||
return createDecipheriv(suite, keys.key, keys.iv) | ||
} | ||
exports.createDecipher = createDecipher | ||
exports.createDecipheriv = createDecipheriv |
@@ -0,21 +1,22 @@ | ||
var MODES = require('./modes') | ||
var AuthCipher = require('./authCipher') | ||
var Buffer = require('safe-buffer').Buffer | ||
var StreamCipher = require('./streamCipher') | ||
var Transform = require('cipher-base') | ||
var aes = require('./aes') | ||
var Transform = require('cipher-base') | ||
var ebtk = require('evp_bytestokey') | ||
var inherits = require('inherits') | ||
var modes = require('./modes') | ||
var ebtk = require('evp_bytestokey') | ||
var StreamCipher = require('./streamCipher') | ||
var AuthCipher = require('./authCipher') | ||
inherits(Cipher, Transform) | ||
function Cipher (mode, key, iv) { | ||
if (!(this instanceof Cipher)) { | ||
return new Cipher(mode, key, iv) | ||
} | ||
Transform.call(this) | ||
this._cache = new Splitter() | ||
this._cipher = new aes.AES(key) | ||
this._prev = new Buffer(iv.length) | ||
iv.copy(this._prev) | ||
this._prev = Buffer.from(iv) | ||
this._mode = mode | ||
this._autopadding = true | ||
} | ||
inherits(Cipher, Transform) | ||
Cipher.prototype._update = function (data) { | ||
@@ -26,2 +27,3 @@ this._cache.add(data) | ||
var out = [] | ||
while ((chunk = this._cache.get())) { | ||
@@ -31,4 +33,8 @@ thing = this._mode.encrypt(this, chunk) | ||
} | ||
return Buffer.concat(out) | ||
} | ||
var PADDING = Buffer.alloc(16, 0x10) | ||
Cipher.prototype._final = function () { | ||
@@ -40,3 +46,5 @@ var chunk = this._cache.flush() | ||
return chunk | ||
} else if (chunk.toString('hex') !== '10101010101010101010101010101010') { | ||
} | ||
if (!chunk.equals(PADDING)) { | ||
this._cipher.scrub() | ||
@@ -46,2 +54,3 @@ throw new Error('data not multiple of block length') | ||
} | ||
Cipher.prototype.setAutoPadding = function (setTo) { | ||
@@ -53,7 +62,5 @@ this._autopadding = !!setTo | ||
function Splitter () { | ||
if (!(this instanceof Splitter)) { | ||
return new Splitter() | ||
} | ||
this.cache = new Buffer('') | ||
this.cache = Buffer.allocUnsafe(0) | ||
} | ||
Splitter.prototype.add = function (data) { | ||
@@ -71,5 +78,6 @@ this.cache = Buffer.concat([this.cache, data]) | ||
} | ||
Splitter.prototype.flush = function () { | ||
var len = 16 - this.cache.length | ||
var padBuff = new Buffer(len) | ||
var padBuff = Buffer.allocUnsafe(len) | ||
@@ -80,45 +88,29 @@ var i = -1 | ||
} | ||
var out = Buffer.concat([this.cache, padBuff]) | ||
return out | ||
return Buffer.concat([this.cache, padBuff]) | ||
} | ||
var modelist = { | ||
ECB: require('./modes/ecb'), | ||
CBC: require('./modes/cbc'), | ||
CFB: require('./modes/cfb'), | ||
CFB8: require('./modes/cfb8'), | ||
CFB1: require('./modes/cfb1'), | ||
OFB: require('./modes/ofb'), | ||
CTR: require('./modes/ctr'), | ||
GCM: require('./modes/ctr') | ||
} | ||
function createCipheriv (suite, password, iv) { | ||
var config = modes[suite.toLowerCase()] | ||
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) | ||
} | ||
var config = MODES[suite.toLowerCase()] | ||
if (!config) throw new TypeError('invalid suite type') | ||
if (typeof password === 'string') password = Buffer.from(password) | ||
if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length) | ||
if (typeof iv === 'string') iv = Buffer.from(iv) | ||
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 StreamCipher(config.module, password, iv) | ||
} else if (config.type === 'auth') { | ||
return new AuthCipher(modelist[config.mode], password, iv) | ||
return new AuthCipher(config.module, password, iv) | ||
} | ||
return new Cipher(modelist[config.mode], password, iv) | ||
return new Cipher(config.module, password, iv) | ||
} | ||
function createCipher (suite, password) { | ||
var config = modes[suite.toLowerCase()] | ||
if (!config) { | ||
throw new TypeError('invalid suite type') | ||
} | ||
var config = MODES[suite.toLowerCase()] | ||
if (!config) throw new TypeError('invalid suite type') | ||
var keys = ebtk(password, false, config.key, config.iv) | ||
@@ -125,0 +117,0 @@ return createCipheriv(suite, keys.key, keys.iv) |
85
ghash.js
@@ -1,10 +0,28 @@ | ||
var zeros = new Buffer(16) | ||
zeros.fill(0) | ||
module.exports = GHASH | ||
var Buffer = require('safe-buffer').Buffer | ||
var ZEROES = Buffer.alloc(16, 0) | ||
function toArray (buf) { | ||
return [ | ||
buf.readUInt32BE(0), | ||
buf.readUInt32BE(4), | ||
buf.readUInt32BE(8), | ||
buf.readUInt32BE(12) | ||
] | ||
} | ||
function fromArray (out) { | ||
var buf = Buffer.allocUnsafe(16) | ||
buf.writeUInt32BE(out[0] >>> 0, 0) | ||
buf.writeUInt32BE(out[1] >>> 0, 4) | ||
buf.writeUInt32BE(out[2] >>> 0, 8) | ||
buf.writeUInt32BE(out[3] >>> 0, 12) | ||
return buf | ||
} | ||
function GHASH (key) { | ||
this.h = key | ||
this.state = new Buffer(16) | ||
this.state.fill(0) | ||
this.cache = new Buffer('') | ||
this.state = Buffer.alloc(16, 0) | ||
this.cache = Buffer.allocUnsafe(0) | ||
} | ||
// from http://bitwiseshiftleft.github.io/sjcl/doc/symbols/src/core_gcm.js.html | ||
@@ -23,13 +41,16 @@ // by Juho Vähä-Herttua | ||
var Zi = [0, 0, 0, 0] | ||
var j, xi, lsb_Vi | ||
var j, xi, lsbVi | ||
var i = -1 | ||
while (++i < 128) { | ||
xi = (this.state[~~(i / 8)] & (1 << (7 - i % 8))) !== 0 | ||
xi = (this.state[~~(i / 8)] & (1 << (7 - (i % 8)))) !== 0 | ||
if (xi) { | ||
// Z_i+1 = Z_i ^ V_i | ||
Zi = xor(Zi, Vi) | ||
Zi[0] ^= Vi[0] | ||
Zi[1] ^= Vi[1] | ||
Zi[2] ^= Vi[2] | ||
Zi[3] ^= Vi[3] | ||
} | ||
// Store the value of LSB(V_i) | ||
lsb_Vi = (Vi[3] & 1) !== 0 | ||
lsbVi = (Vi[3] & 1) !== 0 | ||
@@ -43,3 +64,3 @@ // V_i+1 = V_i >> 1 | ||
// If LSB(V_i) is 1, V_i+1 = (V_i >> 1) ^ R | ||
if (lsb_Vi) { | ||
if (lsbVi) { | ||
Vi[0] = Vi[0] ^ (0xe1 << 24) | ||
@@ -50,2 +71,3 @@ } | ||
} | ||
GHASH.prototype.update = function (buf) { | ||
@@ -60,43 +82,12 @@ this.cache = Buffer.concat([this.cache, buf]) | ||
} | ||
GHASH.prototype.final = function (abl, bl) { | ||
if (this.cache.length) { | ||
this.ghash(Buffer.concat([this.cache, zeros], 16)) | ||
this.ghash(Buffer.concat([this.cache, ZEROES], 16)) | ||
} | ||
this.ghash(fromArray([ | ||
0, abl, | ||
0, bl | ||
])) | ||
this.ghash(fromArray([0, abl, 0, bl])) | ||
return this.state | ||
} | ||
function toArray (buf) { | ||
return [ | ||
buf.readUInt32BE(0), | ||
buf.readUInt32BE(4), | ||
buf.readUInt32BE(8), | ||
buf.readUInt32BE(12) | ||
] | ||
} | ||
function fromArray (out) { | ||
out = out.map(fixup_uint32) | ||
var buf = new Buffer(16) | ||
buf.writeUInt32BE(out[0], 0) | ||
buf.writeUInt32BE(out[1], 4) | ||
buf.writeUInt32BE(out[2], 8) | ||
buf.writeUInt32BE(out[3], 12) | ||
return buf | ||
} | ||
var uint_max = Math.pow(2, 32) | ||
function fixup_uint32 (x) { | ||
var ret, x_pos | ||
ret = x > uint_max || x < 0 ? (x_pos = Math.abs(x) % uint_max, x < 0 ? uint_max - x_pos : x_pos) : x | ||
return ret | ||
} | ||
function xor (a, b) { | ||
return [ | ||
a[0] ^ b[0], | ||
a[1] ^ b[1], | ||
a[2] ^ b[2], | ||
a[3] ^ b[3] | ||
] | ||
} | ||
module.exports = GHASH |
@@ -0,5 +1,14 @@ | ||
var Buffer = require('safe-buffer').Buffer | ||
var xor = require('buffer-xor') | ||
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 | ||
} | ||
exports.encrypt = function (self, data, decrypt) { | ||
var out = new Buffer('') | ||
var out = Buffer.allocUnsafe(0) | ||
var len | ||
@@ -10,3 +19,3 @@ | ||
self._cache = self._cipher.encryptBlock(self._prev) | ||
self._prev = new Buffer('') | ||
self._prev = Buffer.allocUnsafe(0) | ||
} | ||
@@ -26,8 +35,1 @@ | ||
} | ||
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 | ||
} |
@@ -0,1 +1,3 @@ | ||
var Buffer = require('safe-buffer').Buffer | ||
function encryptByte (self, byteParam, decrypt) { | ||
@@ -16,20 +18,26 @@ var pad | ||
} | ||
exports.encrypt = function (self, chunk, decrypt) { | ||
var len = chunk.length | ||
var out = new Buffer(len) | ||
function shiftIn (buffer, value) { | ||
var len = buffer.length | ||
var i = -1 | ||
var out = Buffer.allocUnsafe(buffer.length) | ||
buffer = Buffer.concat([buffer, Buffer.from([value])]) | ||
while (++i < len) { | ||
out[i] = encryptByte(self, chunk[i], decrypt) | ||
out[i] = buffer[i] << 1 | buffer[i + 1] >> (7) | ||
} | ||
return out | ||
} | ||
function shiftIn (buffer, value) { | ||
var len = buffer.length | ||
exports.encrypt = function (self, chunk, decrypt) { | ||
var len = chunk.length | ||
var out = Buffer.allocUnsafe(len) | ||
var i = -1 | ||
var out = new Buffer(buffer.length) | ||
buffer = Buffer.concat([buffer, new Buffer([value])]) | ||
while (++i < len) { | ||
out[i] = buffer[i] << 1 | buffer[i + 1] >> (7) | ||
out[i] = encryptByte(self, chunk[i], decrypt) | ||
} | ||
return out | ||
} |
function encryptByte (self, byteParam, decrypt) { | ||
var pad = self._cipher.encryptBlock(self._prev) | ||
var out = pad[0] ^ byteParam | ||
self._prev = Buffer.concat([self._prev.slice(1), new Buffer([decrypt ? byteParam : out])]) | ||
self._prev = Buffer.concat([ | ||
self._prev.slice(1), | ||
Buffer.from([decrypt ? byteParam : out]) | ||
]) | ||
return out | ||
} | ||
exports.encrypt = function (self, chunk, decrypt) { | ||
var len = chunk.length | ||
var out = new Buffer(len) | ||
var out = Buffer.allocUnsafe(len) | ||
var i = -1 | ||
while (++i < len) { | ||
out[i] = encryptByte(self, chunk[i], decrypt) | ||
} | ||
return out | ||
} |
@@ -19,3 +19,3 @@ var xor = require('buffer-xor') | ||
function getBlock (self) { | ||
var out = self._cipher.encryptBlock(self._prev) | ||
var out = self._cipher.encryptBlockRaw(self._prev) | ||
incr32(self._prev) | ||
@@ -25,5 +25,17 @@ return out | ||
var blockSize = 16 | ||
exports.encrypt = function (self, chunk) { | ||
while (self._cache.length < chunk.length) { | ||
self._cache = Buffer.concat([self._cache, getBlock(self)]) | ||
var chunkNum = Math.ceil(chunk.length / blockSize) | ||
var start = self._cache.length | ||
self._cache = Buffer.concat([ | ||
self._cache, | ||
Buffer.allocUnsafe(chunkNum * blockSize) | ||
]) | ||
for (var i = 0; i < chunkNum; i++) { | ||
var out = getBlock(self) | ||
var offset = start + i * blockSize | ||
self._cache.writeUInt32BE(out[0], offset + 0) | ||
self._cache.writeUInt32BE(out[1], offset + 4) | ||
self._cache.writeUInt32BE(out[2], offset + 8) | ||
self._cache.writeUInt32BE(out[3], offset + 12) | ||
} | ||
@@ -30,0 +42,0 @@ var pad = self._cache.slice(0, chunk.length) |
exports.encrypt = function (self, block) { | ||
return self._cipher.encryptBlock(block) | ||
} | ||
exports.decrypt = function (self, block) { | ||
return self._cipher.decryptBlock(block) | ||
} |
{ | ||
"name": "browserify-aes", | ||
"version": "1.0.6", | ||
"version": "1.0.7", | ||
"description": "aes, for browserify", | ||
@@ -11,3 +11,5 @@ "browser": "browser.js", | ||
"scripts": { | ||
"test": "standard && node test/index.js|tspec" | ||
"standard": "standard", | ||
"unit": "node test/index.js | tspec", | ||
"test": "npm run standard && npm run unit" | ||
}, | ||
@@ -30,13 +32,14 @@ "repository": { | ||
"dependencies": { | ||
"buffer-xor": "^1.0.2", | ||
"buffer-xor": "^1.0.3", | ||
"cipher-base": "^1.0.0", | ||
"create-hash": "^1.1.0", | ||
"evp_bytestokey": "^1.0.0", | ||
"inherits": "^2.0.1" | ||
"evp_bytestokey": "^1.0.3", | ||
"inherits": "^2.0.1", | ||
"safe-buffer": "^5.0.1" | ||
}, | ||
"devDependencies": { | ||
"standard": "^3.7.3", | ||
"tap-spec": "^1.0.0", | ||
"tape": "^3.0.0" | ||
"standard": "^9.0.0", | ||
"tap-spec": "^4.1.1", | ||
"tape": "^4.6.3" | ||
} | ||
} |
var aes = require('./aes') | ||
var Buffer = require('safe-buffer').Buffer | ||
var Transform = require('cipher-base') | ||
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._prev = Buffer.from(iv) | ||
this._cache = Buffer.allocUnsafe(0) | ||
this._secCache = Buffer.allocUnsafe(0) | ||
this._decrypt = decrypt | ||
iv.copy(this._prev) | ||
this._mode = mode | ||
} | ||
inherits(StreamCipher, Transform) | ||
StreamCipher.prototype._update = function (chunk) { | ||
return this._mode.encrypt(this, chunk, this._decrypt) | ||
} | ||
StreamCipher.prototype._final = function () { | ||
this._cipher.scrub() | ||
} | ||
module.exports = StreamCipher |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
20
0
28955
6
22
927
1
+ Addedsafe-buffer@^5.0.1
Updatedbuffer-xor@^1.0.3
Updatedevp_bytestokey@^1.0.3