Update the AES128Cipher and AES256Cipher implementations to be more similar

This commit is the first step for extracting a base class for the
`AES128Cipher` and the `AES256Cipher` classes. The objective here is to
make code changes (not altering the logic) to make the implementations
as similar as possible as found by creating a diff of both classes.

In particular, we extract the key size and cycles of repetitions
constants since they are different for AES-128 and AES-256. Moreover, we
rename functions to be similar.

In the `AES256Cipher` class, there was an additional assignment to
`this` in the decryption function. However, this was unnecessary because
the assignment would also be done when the loop was exited.
This commit is contained in:
Tim van der Meij 2018-01-27 22:03:05 +01:00
parent 695a909a93
commit 9a959e4df7
No known key found for this signature in database
GPG Key ID: 8C3FD2925A5F2762

View File

@ -630,6 +630,9 @@ var NullCipher = (function NullCipherClosure() {
})(); })();
var AES128Cipher = (function AES128CipherClosure() { var AES128Cipher = (function AES128CipherClosure() {
const CYCLES_OF_REPETITION = 10;
const KEY_SIZE = 160; // bits
var rcon = new Uint8Array([ var rcon = new Uint8Array([
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
@ -701,6 +704,7 @@ var AES128Cipher = (function AES128CipherClosure() {
0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,
0x55, 0x21, 0x0c, 0x7d]); 0x55, 0x21, 0x0c, 0x7d]);
var mixCol = new Uint8Array(256); var mixCol = new Uint8Array(256);
for (var i = 0; i < 256; i++) { for (var i = 0; i < 256; i++) {
if (i < 128) { if (i < 128) {
@ -754,7 +758,7 @@ var AES128Cipher = (function AES128CipherClosure() {
0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f,
0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]); 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]);
function expandKey128(cipherKey) { function _expandKey(cipherKey) {
var b = 176, result = new Uint8Array(b); var b = 176, result = new Uint8Array(b);
result.set(cipherKey); result.set(cipherKey);
for (var j = 16, i = 1; j < b; ++i) { for (var j = 16, i = 1; j < b; ++i) {
@ -782,16 +786,16 @@ var AES128Cipher = (function AES128CipherClosure() {
return result; return result;
} }
function decrypt128(input, key) { function _decrypt(input, key) {
var state = new Uint8Array(16); var state = new Uint8Array(16);
state.set(input); state.set(input);
var i, j, k; var i, j, k;
var t, u, v; var t, u, v;
// AddRoundKey // AddRoundKey
for (j = 0, k = 160; j < 16; ++j, ++k) { for (j = 0, k = KEY_SIZE; j < 16; ++j, ++k) {
state[j] ^= key[k]; state[j] ^= key[k];
} }
for (i = 9; i >= 1; --i) { for (i = CYCLES_OF_REPETITION - 1; i >= 1; --i) {
// InvShiftRows // InvShiftRows
t = state[13]; t = state[13];
state[13] = state[9]; state[13] = state[9];
@ -822,9 +826,9 @@ var AES128Cipher = (function AES128CipherClosure() {
// InvMixColumns // InvMixColumns
for (j = 0; j < 16; j += 4) { for (j = 0; j < 16; j += 4) {
var s0 = mix[state[j]], s1 = mix[state[j + 1]], var s0 = mix[state[j]], s1 = mix[state[j + 1]],
s2 = mix[state[j + 2]], s3 = mix[state[j + 3]]; s2 = mix[state[j + 2]], s3 = mix[state[j + 3]];
t = (s0 ^ (s1 >>> 8) ^ (s1 << 24) ^ (s2 >>> 16) ^ (s2 << 16) ^ t = (s0 ^ (s1 >>> 8) ^ (s1 << 24) ^ (s2 >>> 16) ^ (s2 << 16) ^
(s3 >>> 24) ^ (s3 << 8)); (s3 >>> 24) ^ (s3 << 8));
state[j] = (t >>> 24) & 0xFF; state[j] = (t >>> 24) & 0xFF;
state[j + 1] = (t >> 16) & 0xFF; state[j + 1] = (t >> 16) & 0xFF;
state[j + 2] = (t >> 8) & 0xFF; state[j + 2] = (t >> 8) & 0xFF;
@ -859,8 +863,8 @@ var AES128Cipher = (function AES128CipherClosure() {
return state; return state;
} }
function encrypt128(input, key) { function _encrypt(input, key) {
var t, u, v, j, k; var t, u, v, i, j, k;
var state = new Uint8Array(16); var state = new Uint8Array(16);
state.set(input); state.set(input);
for (j = 0; j < 16; ++j) { for (j = 0; j < 16; ++j) {
@ -868,7 +872,7 @@ var AES128Cipher = (function AES128CipherClosure() {
state[j] ^= key[j]; state[j] ^= key[j];
} }
for (i = 1; i < 10; i++) { for (i = 1; i < CYCLES_OF_REPETITION; i++) {
// SubBytes // SubBytes
for (j = 0; j < 16; ++j) { for (j = 0; j < 16; ++j) {
state[j] = s[state[j]]; state[j] = s[state[j]];
@ -932,22 +936,23 @@ var AES128Cipher = (function AES128CipherClosure() {
state[11] = u; state[11] = u;
state[15] = t; state[15] = t;
// AddRoundKey // AddRoundKey
for (j = 0, k = 160; j < 16; ++j, ++k) { for (j = 0, k = KEY_SIZE; j < 16; ++j, ++k) {
state[j] ^= key[k]; state[j] ^= key[k];
} }
return state; return state;
} }
function AES128Cipher(key) { function AES128Cipher(key) {
this.key = expandKey128(key); this.key = _expandKey(key);
this.buffer = new Uint8Array(16); this.buffer = new Uint8Array(16);
this.bufferPosition = 0; this.bufferPosition = 0;
} }
function decryptBlock2(data, finalize) { function _decryptBlock2(data, finalize) {
var i, j, ii, sourceLength = data.length, var i, j, ii, sourceLength = data.length,
buffer = this.buffer, bufferLength = this.bufferPosition, buffer = this.buffer, bufferLength = this.bufferPosition,
result = [], iv = this.iv; result = [], iv = this.iv;
for (i = 0; i < sourceLength; ++i) { for (i = 0; i < sourceLength; ++i) {
buffer[bufferLength] = data[i]; buffer[bufferLength] = data[i];
++bufferLength; ++bufferLength;
@ -955,7 +960,7 @@ var AES128Cipher = (function AES128CipherClosure() {
continue; continue;
} }
// buffer is full, decrypting // buffer is full, decrypting
var plain = decrypt128(buffer, this.key); var plain = _decrypt(buffer, this.key);
// xor-ing the IV vector to get plain text // xor-ing the IV vector to get plain text
for (j = 0; j < 16; ++j) { for (j = 0; j < 16; ++j) {
plain[j] ^= iv[j]; plain[j] ^= iv[j];
@ -998,7 +1003,7 @@ var AES128Cipher = (function AES128CipherClosure() {
} }
AES128Cipher.prototype = { AES128Cipher.prototype = {
decryptBlock: function AES128Cipher_decryptBlock(data, finalize) { decryptBlock(data, finalize) {
var i, sourceLength = data.length; var i, sourceLength = data.length;
var buffer = this.buffer, bufferLength = this.bufferPosition; var buffer = this.buffer, bufferLength = this.bufferPosition;
// waiting for IV values -- they are at the start of the stream // waiting for IV values -- they are at the start of the stream
@ -1014,10 +1019,10 @@ var AES128Cipher = (function AES128CipherClosure() {
this.buffer = new Uint8Array(16); this.buffer = new Uint8Array(16);
this.bufferLength = 0; this.bufferLength = 0;
// starting decryption // starting decryption
this.decryptBlock = decryptBlock2; this.decryptBlock = _decryptBlock2;
return this.decryptBlock(data.subarray(16), finalize); return this.decryptBlock(data.subarray(16), finalize);
}, },
encrypt: function AES128Cipher_encrypt(data, iv) { encrypt(data, iv) {
var i, j, ii, sourceLength = data.length, var i, j, ii, sourceLength = data.length,
buffer = this.buffer, bufferLength = this.bufferPosition, buffer = this.buffer, bufferLength = this.bufferPosition,
result = []; result = [];
@ -1035,7 +1040,7 @@ var AES128Cipher = (function AES128CipherClosure() {
} }
// buffer is full, encrypting // buffer is full, encrypting
var cipher = encrypt128(buffer, this.key); var cipher = _encrypt(buffer, this.key);
iv = cipher; iv = cipher;
result.push(cipher); result.push(cipher);
buffer = new Uint8Array(16); buffer = new Uint8Array(16);
@ -1062,6 +1067,9 @@ var AES128Cipher = (function AES128CipherClosure() {
})(); })();
var AES256Cipher = (function AES256CipherClosure() { var AES256Cipher = (function AES256CipherClosure() {
const CYCLES_OF_REPETITION = 14;
const KEY_SIZE = 224; // bits
var s = new Uint8Array([ var s = new Uint8Array([
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
@ -1163,7 +1171,7 @@ var AES256Cipher = (function AES256CipherClosure() {
0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f,
0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]); 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]);
function expandKey256(cipherKey) { function _expandKey(cipherKey) {
var b = 240, result = new Uint8Array(b); var b = 240, result = new Uint8Array(b);
var r = 1; var r = 1;
@ -1207,16 +1215,16 @@ var AES256Cipher = (function AES256CipherClosure() {
return result; return result;
} }
function decrypt256(input, key) { function _decrypt(input, key) {
var state = new Uint8Array(16); var state = new Uint8Array(16);
state.set(input); state.set(input);
var i, j, k; var i, j, k;
var t, u, v; var t, u, v;
// AddRoundKey // AddRoundKey
for (j = 0, k = 224; j < 16; ++j, ++k) { for (j = 0, k = KEY_SIZE; j < 16; ++j, ++k) {
state[j] ^= key[k]; state[j] ^= key[k];
} }
for (i = 13; i >= 1; --i) { for (i = CYCLES_OF_REPETITION - 1; i >= 1; --i) {
// InvShiftRows // InvShiftRows
t = state[13]; t = state[13];
state[13] = state[9]; state[13] = state[9];
@ -1284,7 +1292,7 @@ var AES256Cipher = (function AES256CipherClosure() {
return state; return state;
} }
function encrypt256(input, key) { function _encrypt(input, key) {
var t, u, v, i, j, k; var t, u, v, i, j, k;
var state = new Uint8Array(16); var state = new Uint8Array(16);
state.set(input); state.set(input);
@ -1293,7 +1301,7 @@ var AES256Cipher = (function AES256CipherClosure() {
state[j] ^= key[j]; state[j] ^= key[j];
} }
for (i = 1; i < 14; i++) { for (i = 1; i < CYCLES_OF_REPETITION; i++) {
// SubBytes // SubBytes
for (j = 0; j < 16; ++j) { for (j = 0; j < 16; ++j) {
state[j] = s[state[j]]; state[j] = s[state[j]];
@ -1357,21 +1365,19 @@ var AES256Cipher = (function AES256CipherClosure() {
state[11] = u; state[11] = u;
state[15] = t; state[15] = t;
// AddRoundKey // AddRoundKey
for (j = 0, k = 224; j < 16; ++j, ++k) { for (j = 0, k = KEY_SIZE; j < 16; ++j, ++k) {
state[j] ^= key[k]; state[j] ^= key[k];
} }
return state; return state;
} }
function AES256Cipher(key) { function AES256Cipher(key) {
this.key = expandKey256(key); this.key = _expandKey(key);
this.buffer = new Uint8Array(16); this.buffer = new Uint8Array(16);
this.bufferPosition = 0; this.bufferPosition = 0;
} }
function decryptBlock2(data, finalize) { function _decryptBlock2(data, finalize) {
var i, j, ii, sourceLength = data.length, var i, j, ii, sourceLength = data.length,
buffer = this.buffer, bufferLength = this.bufferPosition, buffer = this.buffer, bufferLength = this.bufferPosition,
result = [], iv = this.iv; result = [], iv = this.iv;
@ -1383,7 +1389,7 @@ var AES256Cipher = (function AES256CipherClosure() {
continue; continue;
} }
// buffer is full, decrypting // buffer is full, decrypting
var plain = decrypt256(buffer, this.key); var plain = _decrypt(buffer, this.key);
// xor-ing the IV vector to get plain text // xor-ing the IV vector to get plain text
for (j = 0; j < 16; ++j) { for (j = 0; j < 16; ++j) {
plain[j] ^= iv[j]; plain[j] ^= iv[j];
@ -1423,11 +1429,10 @@ var AES256Cipher = (function AES256CipherClosure() {
output.set(result[i], j); output.set(result[i], j);
} }
return output; return output;
} }
AES256Cipher.prototype = { AES256Cipher.prototype = {
decryptBlock: function AES256Cipher_decryptBlock(data, finalize, iv) { decryptBlock(data, finalize, iv) {
var i, sourceLength = data.length; var i, sourceLength = data.length;
var buffer = this.buffer, bufferLength = this.bufferPosition; var buffer = this.buffer, bufferLength = this.bufferPosition;
// if not supplied an IV wait for IV values // if not supplied an IV wait for IV values
@ -1449,10 +1454,10 @@ var AES256Cipher = (function AES256CipherClosure() {
this.buffer = new Uint8Array(16); this.buffer = new Uint8Array(16);
this.bufferLength = 0; this.bufferLength = 0;
// starting decryption // starting decryption
this.decryptBlock = decryptBlock2; this.decryptBlock = _decryptBlock2;
return this.decryptBlock(data, finalize); return this.decryptBlock(data, finalize);
}, },
encrypt: function AES256Cipher_encrypt(data, iv) { encrypt(data, iv) {
var i, j, ii, sourceLength = data.length, var i, j, ii, sourceLength = data.length,
buffer = this.buffer, bufferLength = this.bufferPosition, buffer = this.buffer, bufferLength = this.bufferPosition,
result = []; result = [];
@ -1470,8 +1475,8 @@ var AES256Cipher = (function AES256CipherClosure() {
} }
// buffer is full, encrypting // buffer is full, encrypting
var cipher = encrypt256(buffer, this.key); var cipher = _encrypt(buffer, this.key);
this.iv = cipher; iv = cipher;
result.push(cipher); result.push(cipher);
buffer = new Uint8Array(16); buffer = new Uint8Array(16);
bufferLength = 0; bufferLength = 0;