UNPKG

6.64 kBJavaScriptView Raw
1// based on the aes implimentation in triple sec
2// https://github.com/keybase/triplesec
3
4// which is in turn based on the one from crypto-js
5// https://code.google.com/p/crypto-js/
6
7var uint_max = Math.pow(2, 32);
8function fixup_uint32(x) {
9 var ret, x_pos;
10 ret = x > uint_max || x < 0 ? (x_pos = Math.abs(x) % uint_max, x < 0 ? uint_max - x_pos : x_pos) : x;
11 return ret;
12}
13function scrub_vec(v) {
14 var i, _i, _ref;
15 for (i = _i = 0, _ref = v.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
16 v[i] = 0;
17 }
18 return false;
19}
20
21function Global() {
22 var i;
23 this.SBOX = [];
24 this.INV_SBOX = [];
25 this.SUB_MIX = (function() {
26 var _i, _results;
27 _results = [];
28 for (i = _i = 0; _i < 4; i = ++_i) {
29 _results.push([]);
30 }
31 return _results;
32 })();
33 this.INV_SUB_MIX = (function() {
34 var _i, _results;
35 _results = [];
36 for (i = _i = 0; _i < 4; i = ++_i) {
37 _results.push([]);
38 }
39 return _results;
40 })();
41 this.init();
42 this.RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
43}
44
45Global.prototype.init = function() {
46 var d, i, sx, t, x, x2, x4, x8, xi, _i;
47 d = (function() {
48 var _i, _results;
49 _results = [];
50 for (i = _i = 0; _i < 256; i = ++_i) {
51 if (i < 128) {
52 _results.push(i << 1);
53 } else {
54 _results.push((i << 1) ^ 0x11b);
55 }
56 }
57 return _results;
58 })();
59 x = 0;
60 xi = 0;
61 for (i = _i = 0; _i < 256; i = ++_i) {
62 sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);
63 sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63;
64 this.SBOX[x] = sx;
65 this.INV_SBOX[sx] = x;
66 x2 = d[x];
67 x4 = d[x2];
68 x8 = d[x4];
69 t = (d[sx] * 0x101) ^ (sx * 0x1010100);
70 this.SUB_MIX[0][x] = (t << 24) | (t >>> 8);
71 this.SUB_MIX[1][x] = (t << 16) | (t >>> 16);
72 this.SUB_MIX[2][x] = (t << 8) | (t >>> 24);
73 this.SUB_MIX[3][x] = t;
74 t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100);
75 this.INV_SUB_MIX[0][sx] = (t << 24) | (t >>> 8);
76 this.INV_SUB_MIX[1][sx] = (t << 16) | (t >>> 16);
77 this.INV_SUB_MIX[2][sx] = (t << 8) | (t >>> 24);
78 this.INV_SUB_MIX[3][sx] = t;
79 if (x === 0) {
80 x = xi = 1;
81 } else {
82 x = x2 ^ d[d[d[x8 ^ x2]]];
83 xi ^= d[d[xi]];
84 }
85 }
86 return true;
87};
88
89var G = new Global();
90
91
92AES.blockSize = 4 * 4;
93
94AES.prototype.blockSize = AES.blockSize;
95
96AES.keySize = 256 / 8;
97
98AES.prototype.keySize = AES.keySize;
99
100 function bufferToArray(buf) {
101 var len = buf.length/4;
102 var out = new Array(len);
103 var i = -1;
104 while (++i < len) {
105 out[i] = buf.readUInt32BE(i * 4);
106 }
107 return out;
108 }
109function AES(key) {
110 this._key = bufferToArray(key);
111 this._doReset();
112}
113
114AES.prototype._doReset = function() {
115 var invKsRow, keySize, keyWords, ksRow, ksRows, t, _i, _j;
116 keyWords = this._key;
117 keySize = keyWords.length;
118 this._nRounds = keySize + 6;
119 ksRows = (this._nRounds + 1) * 4;
120 this._keySchedule = [];
121 for (ksRow = _i = 0; 0 <= ksRows ? _i < ksRows : _i > ksRows; ksRow = 0 <= ksRows ? ++_i : --_i) {
122 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);
123 }
124 this._invKeySchedule = [];
125 for (invKsRow = _j = 0; 0 <= ksRows ? _j < ksRows : _j > ksRows; invKsRow = 0 <= ksRows ? ++_j : --_j) {
126 ksRow = ksRows - invKsRow;
127 t = this._keySchedule[ksRow - (invKsRow % 4 ? 0 : 4)];
128 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]];
129 }
130 return true;
131};
132
133AES.prototype.encryptBlock = function(M) {
134 M = bufferToArray(new Buffer(M));
135 var out = this._doCryptBlock(M, this._keySchedule, G.SUB_MIX, G.SBOX);
136 var buf = new Buffer(16);
137 buf.writeUInt32BE(out[0], 0);
138 buf.writeUInt32BE(out[1], 4);
139 buf.writeUInt32BE(out[2], 8);
140 buf.writeUInt32BE(out[3], 12);
141 return buf;
142};
143
144AES.prototype.decryptBlock = function(M) {
145 M = bufferToArray(new Buffer(M));
146 var temp = [M[3], M[1]];
147 M[1] = temp[0];
148 M[3] = temp[1];
149 var out = this._doCryptBlock(M, this._invKeySchedule, G.INV_SUB_MIX, G.INV_SBOX);
150 var buf = new Buffer(16);
151 buf.writeUInt32BE(out[0], 0);
152 buf.writeUInt32BE(out[3], 4);
153 buf.writeUInt32BE(out[2], 8);
154 buf.writeUInt32BE(out[1], 12);
155 return buf;
156};
157
158AES.prototype.scrub = function() {
159 scrub_vec(this._keySchedule);
160 scrub_vec(this._invKeySchedule);
161 scrub_vec(this._key);
162};
163
164AES.prototype._doCryptBlock = function(M, keySchedule, SUB_MIX, SBOX) {
165 var ksRow, round, s0, s1, s2, s3, t0, t1, t2, t3, _i, _ref;
166
167 s0 = M[0] ^ keySchedule[0];
168 s1 = M[1] ^ keySchedule[1];
169 s2 = M[2] ^ keySchedule[2];
170 s3 = M[3] ^ keySchedule[3];
171 ksRow = 4;
172 for (round = _i = 1, _ref = this._nRounds; 1 <= _ref ? _i < _ref : _i > _ref; round = 1 <= _ref ? ++_i : --_i) {
173 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++];
174 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++];
175 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++];
176 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++];
177 s0 = t0;
178 s1 = t1;
179 s2 = t2;
180 s3 = t3;
181 }
182 t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++];
183 t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++];
184 t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++];
185 t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++];
186 return [
187 fixup_uint32(t0),
188 fixup_uint32(t1),
189 fixup_uint32(t2),
190 fixup_uint32(t3)
191 ];
192
193};
194
195
196
197
198 exports.AES = AES;
\No newline at end of file