├── .gitignore
├── .npmignore
├── LICENSE.txt
├── README.md
├── bower.json
├── generate-tests.py
├── index.js
├── package.json
└── test
├── index.js
├── test-aes.js
├── test-buffer.js
├── test-counter.js
├── test-errors.js
├── test-padding.js
├── test-vectors.json
└── test.html
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | bower_components/
3 | test/
4 | generate-tests.py
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Richard Moore
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | AES-JS
2 | ======
3 |
4 | [](https://badge.fury.io/js/aes-js)
5 |
6 | A pure JavaScript implementation of the AES block cipher algorithm and all common modes of operation (CBC, CFB, CTR, ECB and OFB).
7 |
8 | Features
9 | --------
10 |
11 | - Pure JavaScript (with no dependencies)
12 | - Supports all key sizes (128-bit, 192-bit and 256-bit)
13 | - Supports all common modes of operation (CBC, CFB, CTR, ECB and OFB)
14 | - Works in either node.js or web browsers
15 |
16 | Migrating from 2.x to 3.x
17 | -------------------------
18 |
19 | The utility functions have been renamed in the 3.x branch, since they were causing a great deal of confusion converting between bytes and string.
20 |
21 | The examples have also been updated to encode binary data as printable hex strings.
22 |
23 | **Strings and Bytes**
24 |
25 | Strings should **NOT** be used as keys. UTF-8 allows variable length, multi-byte characters, so a string that is 16 *characters* long may not be 16 *bytes* long.
26 |
27 | Also, UTF8 should **NOT** be used to store arbitrary binary data as it is a *string* encoding format, not a *binary* encoding format.
28 |
29 | ```javascript
30 | // aesjs.util.convertStringToBytes(aString)
31 | // Becomes:
32 | aesjs.utils.utf8.toBytes(aString)
33 |
34 |
35 | // aesjs.util.convertBytesToString(aString)
36 | // Becomes:
37 | aesjs.utils.utf8.fromBytes(aString)
38 | ```
39 |
40 | **Bytes and Hex strings**
41 |
42 | Binary data, such as encrypted bytes, can safely be stored and printed as hexidecimal strings.
43 |
44 | ```javascript
45 | // aesjs.util.convertStringToBytes(aString, 'hex')
46 | // Becomes:
47 | aesjs.utils.hex.toBytes(aString)
48 |
49 |
50 | // aesjs.util.convertBytesToString(aString, 'hex')
51 | // Becomes:
52 | aesjs.utils.hex.fromBytes(aString)
53 | ```
54 |
55 | **Typed Arrays**
56 |
57 | The 3.x and above versions of aes-js use [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) instead of Array, which reduces code size when used with Browserify (it no longer pulls in Buffer) and is also about **twice** the speed.
58 |
59 | However, if you need to support browsers older than IE 10, you should continue using version 2.x.
60 |
61 |
62 | API
63 | ===
64 |
65 | #### Node.js
66 |
67 | To install `aes-js` in your node.js project:
68 |
69 | ```
70 | npm install aes-js
71 | ```
72 |
73 | And to access it from within node, simply add:
74 |
75 | ```javascript
76 | var aesjs = require('aes-js');
77 | ```
78 |
79 | #### Web Browser
80 |
81 | To use `aes-js` in a web page, add the following:
82 |
83 | ```html
84 |
85 | ```
86 |
87 | Keys
88 | ----
89 |
90 | All keys must be 128 bits (16 bytes), 192 bits (24 bytes) or 256 bits (32 bytes) long.
91 |
92 | The library work with `Array`, `Uint8Array` and `Buffer` objects as well as any *array-like* object (i.e. must have a `length` property, and have a valid byte value for each entry).
93 |
94 | ```javascript
95 | // 128-bit, 192-bit and 256-bit keys
96 | var key_128 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
97 | var key_192 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
98 | 16, 17, 18, 19, 20, 21, 22, 23];
99 | var key_256 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
100 | 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
101 | 29, 30, 31];
102 |
103 | // or, you may use Uint8Array:
104 | var key_128_array = new Uint8Array(key_128);
105 | var key_192_array = new Uint8Array(key_192);
106 | var key_256_array = new Uint8Array(key_256);
107 |
108 | // or, you may use Buffer in node.js:
109 | var key_128_buffer = Buffer.from(key_128);
110 | var key_192_buffer = Buffer.from(key_192);
111 | var key_256_buffer = Buffer.from(key_256);
112 | ```
113 |
114 |
115 | To generate keys from simple-to-remember passwords, consider using a password-based key-derivation function such as [scrypt](https://www.npmjs.com/package/scrypt-js) or [bcrypt](https://www.npmjs.com/search?q=bcrypt).
116 |
117 |
118 | Common Modes of Operation
119 | -------------------------
120 |
121 | There are several modes of operations, each with various pros and cons. In general though, the **CBC** and **CTR** modes are recommended. The **ECB is NOT recommended.**, and is included primarily for completeness.
122 |
123 | ### CTR - Counter (recommended)
124 |
125 | ```javascript
126 | // An example 128-bit key (16 bytes * 8 bits/byte = 128 bits)
127 | var key = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ];
128 |
129 | // Convert text to bytes
130 | var text = 'Text may be any length you wish, no padding is required.';
131 | var textBytes = aesjs.utils.utf8.toBytes(text);
132 |
133 | // The counter is optional, and if omitted will begin at 1
134 | var aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5));
135 | var encryptedBytes = aesCtr.encrypt(textBytes);
136 |
137 | // To print or store the binary data, you may convert it to hex
138 | var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
139 | console.log(encryptedHex);
140 | // "a338eda3874ed884b6199150d36f49988c90f5c47fe7792b0cf8c7f77eeffd87
141 | // ea145b73e82aefcf2076f881c88879e4e25b1d7b24ba2788"
142 |
143 | // When ready to decrypt the hex string, convert it back to bytes
144 | var encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex);
145 |
146 | // The counter mode of operation maintains internal state, so to
147 | // decrypt a new instance must be instantiated.
148 | var aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5));
149 | var decryptedBytes = aesCtr.decrypt(encryptedBytes);
150 |
151 | // Convert our bytes back into text
152 | var decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes);
153 | console.log(decryptedText);
154 | // "Text may be any length you wish, no padding is required."
155 | ```
156 |
157 |
158 | ### CBC - Cipher-Block Chaining (recommended)
159 |
160 | ```javascript
161 | // An example 128-bit key
162 | var key = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ];
163 |
164 | // The initialization vector (must be 16 bytes)
165 | var iv = [ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,35, 36 ];
166 |
167 | // Convert text to bytes (text must be a multiple of 16 bytes)
168 | var text = 'TextMustBe16Byte';
169 | var textBytes = aesjs.utils.utf8.toBytes(text);
170 |
171 | var aesCbc = new aesjs.ModeOfOperation.cbc(key, iv);
172 | var encryptedBytes = aesCbc.encrypt(textBytes);
173 |
174 | // To print or store the binary data, you may convert it to hex
175 | var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
176 | console.log(encryptedHex);
177 | // "104fb073f9a131f2cab49184bb864ca2"
178 |
179 | // When ready to decrypt the hex string, convert it back to bytes
180 | var encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex);
181 |
182 | // The cipher-block chaining mode of operation maintains internal
183 | // state, so to decrypt a new instance must be instantiated.
184 | var aesCbc = new aesjs.ModeOfOperation.cbc(key, iv);
185 | var decryptedBytes = aesCbc.decrypt(encryptedBytes);
186 |
187 | // Convert our bytes back into text
188 | var decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes);
189 | console.log(decryptedText);
190 | // "TextMustBe16Byte"
191 | ```
192 |
193 |
194 | ### CFB - Cipher Feedback
195 |
196 | ```javascript
197 | // An example 128-bit key
198 | var key = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ];
199 |
200 | // The initialization vector (must be 16 bytes)
201 | var iv = [ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,35, 36 ];
202 |
203 | // Convert text to bytes (must be a multiple of the segment size you choose below)
204 | var text = 'TextMustBeAMultipleOfSegmentSize';
205 | var textBytes = aesjs.utils.utf8.toBytes(text);
206 |
207 | // The segment size is optional, and defaults to 1
208 | var segmentSize = 8;
209 | var aesCfb = new aesjs.ModeOfOperation.cfb(key, iv, segmentSize);
210 | var encryptedBytes = aesCfb.encrypt(textBytes);
211 |
212 | // To print or store the binary data, you may convert it to hex
213 | var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
214 | console.log(encryptedHex);
215 | // "55e3af2638c560b4fdb9d26a630733ea60197ec23deb85b1f60f71f10409ce27"
216 |
217 | // When ready to decrypt the hex string, convert it back to bytes
218 | var encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex);
219 |
220 | // The cipher feedback mode of operation maintains internal state,
221 | // so to decrypt a new instance must be instantiated.
222 | var aesCfb = new aesjs.ModeOfOperation.cfb(key, iv, 8);
223 | var decryptedBytes = aesCfb.decrypt(encryptedBytes);
224 |
225 | // Convert our bytes back into text
226 | var decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes);
227 | console.log(decryptedText);
228 | // "TextMustBeAMultipleOfSegmentSize"
229 | ```
230 |
231 |
232 | ### OFB - Output Feedback
233 |
234 | ```javascript
235 | // An example 128-bit key
236 | var key = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ];
237 |
238 | // The initialization vector (must be 16 bytes)
239 | var iv = [ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,35, 36 ];
240 |
241 | // Convert text to bytes
242 | var text = 'Text may be any length you wish, no padding is required.';
243 | var textBytes = aesjs.utils.utf8.toBytes(text);
244 |
245 | var aesOfb = new aesjs.ModeOfOperation.ofb(key, iv);
246 | var encryptedBytes = aesOfb.encrypt(textBytes);
247 |
248 | // To print or store the binary data, you may convert it to hex
249 | var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
250 | console.log(encryptedHex);
251 | // "55e3af2655dd72b9f32456042f39bae9accff6259159e608be55a1aa313c598d
252 | // b4b18406d89c83841c9d1af13b56de8eda8fcfe9ec8e75e8"
253 |
254 | // When ready to decrypt the hex string, convert it back to bytes
255 | var encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex);
256 |
257 | // The output feedback mode of operation maintains internal state,
258 | // so to decrypt a new instance must be instantiated.
259 | var aesOfb = new aesjs.ModeOfOperation.ofb(key, iv);
260 | var decryptedBytes = aesOfb.decrypt(encryptedBytes);
261 |
262 | // Convert our bytes back into text
263 | var decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes);
264 | console.log(decryptedText);
265 | // "Text may be any length you wish, no padding is required."
266 | ```
267 |
268 |
269 | ### ECB - Electronic Codebook (NOT recommended)
270 |
271 | This mode is **not** recommended. Since, for a given key, the same plaintext block in produces the same ciphertext block out, this mode of operation can leak data, such as patterns. For more details and examples, see the Wikipedia article, [Electronic Codebook](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29).
272 |
273 | ```javascript
274 | // An example 128-bit key
275 | var key = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ];
276 |
277 | // Convert text to bytes
278 | var text = 'TextMustBe16Byte';
279 | var textBytes = aesjs.utils.utf8.toBytes(text);
280 |
281 | var aesEcb = new aesjs.ModeOfOperation.ecb(key);
282 | var encryptedBytes = aesEcb.encrypt(textBytes);
283 |
284 | // To print or store the binary data, you may convert it to hex
285 | var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
286 | console.log(encryptedHex);
287 | // "a7d93b35368519fac347498dec18b458"
288 |
289 | // When ready to decrypt the hex string, convert it back to bytes
290 | var encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex);
291 |
292 | // Since electronic codebook does not store state, we can
293 | // reuse the same instance.
294 | //var aesEcb = new aesjs.ModeOfOperation.ecb(key);
295 | var decryptedBytes = aesEcb.decrypt(encryptedBytes);
296 |
297 | // Convert our bytes back into text
298 | var decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes);
299 | console.log(decryptedText);
300 | // "TextMustBe16Byte"
301 | ```
302 |
303 |
304 |
305 | Block Cipher
306 | ------------
307 |
308 | You should usually use one of the above common modes of operation. Using the block cipher algorithm directly is also possible using **ECB** as that mode of operation is merely a thin wrapper.
309 |
310 | But this might be useful to experiment with custom modes of operation or play with block cipher algorithms.
311 |
312 | ```javascript
313 |
314 | // the AES block cipher algorithm works on 16 byte bloca ks, no more, no less
315 | var text = "ABlockIs16Bytes!";
316 | var textAsBytes = aesjs.utils.utf8.toBytes(text)
317 | console.log(textAsBytes);
318 | // [65, 66, 108, 111, 99, 107, 73, 115, 49, 54, 66, 121, 116, 101, 115, 33]
319 |
320 | // create an instance of the block cipher algorithm
321 | var key = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3];
322 | var aes = new aesjs.AES(key);
323 |
324 | // encrypt...
325 | var encryptedBytes = aes.encrypt(textAsBytes);
326 | console.log(encryptedBytes);
327 | // [136, 15, 199, 174, 118, 133, 233, 177, 143, 47, 42, 211, 96, 55, 107, 109]
328 |
329 | // To print or store the binary data, you may convert it to hex
330 | var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
331 | console.log(encryptedHex);
332 | // "880fc7ae7685e9b18f2f2ad360376b6d"
333 |
334 | // When ready to decrypt the hex string, convert it back to bytes
335 | var encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex);
336 |
337 | // decrypt...
338 | var decryptedBytes = aes.decrypt(encryptedBytes);
339 | console.log(decryptedBytes);
340 | // [65, 66, 108, 111, 99, 107, 73, 115, 49, 54, 66, 121, 116, 101, 115, 33]
341 |
342 |
343 | // decode the bytes back into our original text
344 | var decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes);
345 | console.log(decryptedText);
346 | // "ABlockIs16Bytes!"
347 | ```
348 |
349 |
350 | Notes
351 | =====
352 |
353 | What is a Key
354 | -------------
355 |
356 | This seems to be a point of confusion for many people new to using encryption. You can think of the key as the *"password"*. However, these algorithms require the *"password"* to be a specific length.
357 |
358 | With AES, there are three possible key lengths, 128-bit (16 bytes), 192-bit (24 bytes) or 256-bit (32 bytes). When you create an AES object, the key size is automatically detected, so it is important to pass in a key of the correct length.
359 |
360 | Often, you wish to provide a password of arbitrary length, for example, something easy to remember or write down. In these cases, you must come up with a way to transform the password into a key of a specific length. A **Password-Based Key Derivation Function** (PBKDF) is an algorithm designed for this exact purpose.
361 |
362 | Here is an example, using the popular (possibly obsolete?) pbkdf2:
363 |
364 | ```javascript
365 | var pbkdf2 = require('pbkdf2');
366 |
367 | var key_128 = pbkdf2.pbkdf2Sync('password', 'salt', 1, 128 / 8, 'sha512');
368 | var key_192 = pbkdf2.pbkdf2Sync('password', 'salt', 1, 192 / 8, 'sha512');
369 | var key_256 = pbkdf2.pbkdf2Sync('password', 'salt', 1, 256 / 8, 'sha512');
370 | ```
371 |
372 | Another possibility, is to use a hashing function, such as SHA256 to hash the password, but this method is vulnerable to [Rainbow Attacks](http://en.wikipedia.org/wiki/Rainbow_table), unless you use a [salt](http://en.wikipedia.org/wiki/Salt_(cryptography)).
373 |
374 | Performance
375 | -----------
376 |
377 | Todo...
378 |
379 | Tests
380 | -----
381 |
382 | A test suite has been generated (`test/test-vectors.json`) from a known correct implementation, [pycrypto](https://www.dlitz.net/software/pycrypto/). To generate new test vectors, run `python generate-tests.py`.
383 |
384 | To run the node.js test suite:
385 |
386 | ```
387 | npm test
388 | ```
389 |
390 | To run the web browser tests, open the `test/test.html` file in your browser.
391 |
392 | FAQ
393 | ---
394 |
395 | #### How do I get a question I have added?
396 |
397 | E-mail me at aes-js@ricmoo.com with any questions, suggestions, comments, et cetera.
398 |
399 |
400 | Donations
401 | ---------
402 |
403 | Obviously, it's all licensed under the MIT license, so use it as you wish; but if you'd like to buy me a coffee, I won't complain. =)
404 |
405 | - Bitcoin - `1K1Ax9t6uJmjE4X5xcoVuyVTsiLrYRqe2P`
406 | - Ethereum - `0x70bDC274028F3f391E398dF8e3977De64FEcBf04`
407 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "aes-js",
3 | "description": "A pure JavaScript implementation of the AES block cipher and all common modes of operation.",
4 | "main": "index.js",
5 | "authors": [
6 | "Richard Moore "
7 | ],
8 | "license": "MIT",
9 | "keywords": [
10 | "aes",
11 | "aes-ctr",
12 | "aes-ofb",
13 | "aes-ecb",
14 | "aes-cbc",
15 | "aes-cfb",
16 | "encrypt",
17 | "decrypt",
18 | "block",
19 | "cipher"
20 | ],
21 | "homepage": "https://github.com/ricmoo/aes-js",
22 | "moduleType": [
23 | "globals"
24 | ],
25 | "ignore": [
26 | "**/.*",
27 | "node_modules",
28 | "bower_components",
29 | "test",
30 | "tests"
31 | ]
32 | }
33 |
--------------------------------------------------------------------------------
/generate-tests.py:
--------------------------------------------------------------------------------
1 | # The MIT License (MIT)
2 | #
3 | # Copyright (c) 2014 Richard Moore
4 | #
5 | # Permission is hereby granted, free of charge, to any person obtaining a copy
6 | # of this software and associated documentation files (the "Software"), to deal
7 | # in the Software without restriction, including without limitation the rights
8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the Software is
10 | # furnished to do so, subject to the following conditions:
11 | #
12 | # The above copyright notice and this permission notice shall be included in
13 | # all copies or substantial portions of the Software.
14 | #
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | # THE SOFTWARE.
22 |
23 |
24 | # This file is a modified version of the test suite for pyaes (https://www.github.com/ricmoo/pyaes/)
25 |
26 |
27 | import json
28 |
29 | class NoIndent(object):
30 | def __init__(self, value):
31 | self.value = value
32 |
33 | def default(o, encoder=json.JSONEncoder()):
34 | if isinstance(o, NoIndent):
35 | return '__' + json.dumps(o.value) + '__'
36 | return encoder.default(o)
37 |
38 |
39 | import os, time
40 |
41 | Tests = []
42 |
43 | # compare against a known working implementation
44 | from Crypto.Cipher import AES as KAES
45 | from Crypto.Util import Counter as KCounter
46 | for mode in [ 'CBC', 'CTR', 'CFB', 'ECB', 'OFB' ]:
47 |
48 | (tt_ksetup, tt_kencrypt, tt_kdecrypt) = (0.0, 0.0, 0.0)
49 | (tt_setup, tt_encrypt, tt_decrypt) = (0.0, 0.0, 0.0)
50 | count = 0
51 |
52 | for key_size in (128, 192, 256):
53 |
54 | for test in xrange(1, 8):
55 | key = os.urandom(key_size // 8)
56 |
57 | iv = None
58 | segment_size = None
59 |
60 | if mode == 'CBC':
61 | iv = os.urandom(16)
62 |
63 | text_length = [None, 16, 16, 16, 32, 48, 64, 64, 64][test]
64 | if test == 1:
65 | plaintext = [ '' ]
66 | else:
67 | plaintext = [ os.urandom(text_length) for x in xrange(0, test) ]
68 |
69 | kaes = KAES.new(key, KAES.MODE_CBC, IV = iv)
70 | kaes2 = KAES.new(key, KAES.MODE_CBC, IV = iv)
71 |
72 | elif mode == 'CFB':
73 | iv = os.urandom(16)
74 | plaintext = [ os.urandom(test * 5) for x in xrange(0, test) ]
75 |
76 | kaes = KAES.new(key, KAES.MODE_CFB, IV = iv, segment_size = test * 8)
77 | kaes2 = KAES.new(key, KAES.MODE_CFB, IV = iv, segment_size = test * 8)
78 |
79 | segment_size = test
80 |
81 | elif mode == 'ECB':
82 | text_length = [None, 16, 16, 16, 32, 48, 64, 64, 64][test]
83 | if test == 1:
84 | plaintext = [ '' ]
85 | else:
86 | plaintext = [ os.urandom(text_length) for x in xrange(0, test) ]
87 |
88 | kaes = KAES.new(key, KAES.MODE_ECB)
89 | kaes2 = KAES.new(key, KAES.MODE_ECB)
90 |
91 | elif mode == 'OFB':
92 | iv = os.urandom(16)
93 | plaintext = [ os.urandom(16) for x in xrange(0, test) ]
94 |
95 | kaes = KAES.new(key, KAES.MODE_OFB, IV = iv)
96 | kaes2 = KAES.new(key, KAES.MODE_OFB, IV = iv)
97 |
98 | elif mode == 'CTR':
99 | text_length = [None, 3, 16, 127, 128, 129, 1500, 10000, 100000, 10001, 10002, 10003, 10004, 10005, 10006, 10007, 10008][test]
100 | if test < 6:
101 | plaintext = [ os.urandom(text_length) ]
102 | else:
103 | plaintext = [ os.urandom(text_length) for x in xrange(0, test) ]
104 |
105 | kaes = KAES.new(key, KAES.MODE_CTR, counter = KCounter.new(128, initial_value = 0))
106 | kaes2 = KAES.new(key, KAES.MODE_CTR, counter = KCounter.new(128, initial_value = 0))
107 |
108 | count += 1
109 |
110 | kenc = [kaes.encrypt(p) for p in plaintext]
111 |
112 | iv_enc = None
113 | if iv:
114 | iv_enc = NoIndent([ord(x) for x in iv])
115 | Tests.append(dict(
116 | encrypted = [NoIndent([ord(x) for x in chunk]) for chunk in kenc],
117 | iv = iv_enc,
118 | key = NoIndent([ord(x) for x in key]),
119 | modeOfOperation = mode.lower(),
120 | plaintext = [NoIndent([ord(x) for x in chunk]) for chunk in plaintext],
121 | segmentSize = segment_size,
122 | ))
123 |
124 | dt1 = [kaes2.decrypt(k) for k in kenc]
125 |
126 | print json.dumps(Tests, indent = 4, sort_keys = True, default = default).replace('"__', '').replace('__"', '')
127 |
128 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /*! MIT License. Copyright 2015-2018 Richard Moore . See LICENSE.txt. */
2 | (function(root) {
3 | "use strict";
4 |
5 | function checkInt(value) {
6 | return (parseInt(value) === value);
7 | }
8 |
9 | function checkInts(arrayish) {
10 | if (!checkInt(arrayish.length)) { return false; }
11 |
12 | for (var i = 0; i < arrayish.length; i++) {
13 | if (!checkInt(arrayish[i]) || arrayish[i] < 0 || arrayish[i] > 255) {
14 | return false;
15 | }
16 | }
17 |
18 | return true;
19 | }
20 |
21 | function coerceArray(arg, copy) {
22 |
23 | // ArrayBuffer view
24 | if (arg.buffer && arg.name === 'Uint8Array') {
25 |
26 | if (copy) {
27 | if (arg.slice) {
28 | arg = arg.slice();
29 | } else {
30 | arg = Array.prototype.slice.call(arg);
31 | }
32 | }
33 |
34 | return arg;
35 | }
36 |
37 | // It's an array; check it is a valid representation of a byte
38 | if (Array.isArray(arg)) {
39 | if (!checkInts(arg)) {
40 | throw new Error('Array contains invalid value: ' + arg);
41 | }
42 |
43 | return new Uint8Array(arg);
44 | }
45 |
46 | // Something else, but behaves like an array (maybe a Buffer? Arguments?)
47 | if (checkInt(arg.length) && checkInts(arg)) {
48 | return new Uint8Array(arg);
49 | }
50 |
51 | throw new Error('unsupported array-like object');
52 | }
53 |
54 | function createArray(length) {
55 | return new Uint8Array(length);
56 | }
57 |
58 | function copyArray(sourceArray, targetArray, targetStart, sourceStart, sourceEnd) {
59 | if (sourceStart != null || sourceEnd != null) {
60 | if (sourceArray.slice) {
61 | sourceArray = sourceArray.slice(sourceStart, sourceEnd);
62 | } else {
63 | sourceArray = Array.prototype.slice.call(sourceArray, sourceStart, sourceEnd);
64 | }
65 | }
66 | targetArray.set(sourceArray, targetStart);
67 | }
68 |
69 |
70 |
71 | var convertUtf8 = (function() {
72 | function toBytes(text) {
73 | var result = [], i = 0;
74 | text = encodeURI(text);
75 | while (i < text.length) {
76 | var c = text.charCodeAt(i++);
77 |
78 | // if it is a % sign, encode the following 2 bytes as a hex value
79 | if (c === 37) {
80 | result.push(parseInt(text.substr(i, 2), 16))
81 | i += 2;
82 |
83 | // otherwise, just the actual byte
84 | } else {
85 | result.push(c)
86 | }
87 | }
88 |
89 | return coerceArray(result);
90 | }
91 |
92 | function fromBytes(bytes) {
93 | var result = [], i = 0;
94 |
95 | while (i < bytes.length) {
96 | var c = bytes[i];
97 |
98 | if (c < 128) {
99 | result.push(String.fromCharCode(c));
100 | i++;
101 | } else if (c > 191 && c < 224) {
102 | result.push(String.fromCharCode(((c & 0x1f) << 6) | (bytes[i + 1] & 0x3f)));
103 | i += 2;
104 | } else {
105 | result.push(String.fromCharCode(((c & 0x0f) << 12) | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f)));
106 | i += 3;
107 | }
108 | }
109 |
110 | return result.join('');
111 | }
112 |
113 | return {
114 | toBytes: toBytes,
115 | fromBytes: fromBytes,
116 | }
117 | })();
118 |
119 | var convertHex = (function() {
120 | function toBytes(text) {
121 | var result = [];
122 | for (var i = 0; i < text.length; i += 2) {
123 | result.push(parseInt(text.substr(i, 2), 16));
124 | }
125 |
126 | return result;
127 | }
128 |
129 | // http://ixti.net/development/javascript/2011/11/11/base64-encodedecode-of-utf8-in-browser-with-js.html
130 | var Hex = '0123456789abcdef';
131 |
132 | function fromBytes(bytes) {
133 | var result = [];
134 | for (var i = 0; i < bytes.length; i++) {
135 | var v = bytes[i];
136 | result.push(Hex[(v & 0xf0) >> 4] + Hex[v & 0x0f]);
137 | }
138 | return result.join('');
139 | }
140 |
141 | return {
142 | toBytes: toBytes,
143 | fromBytes: fromBytes,
144 | }
145 | })();
146 |
147 |
148 | // Number of rounds by keysize
149 | var numberOfRounds = {16: 10, 24: 12, 32: 14}
150 |
151 | // Round constant words
152 | var rcon = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91];
153 |
154 | // S-box and Inverse S-box (S is for Substitution)
155 | var S = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16];
156 | var Si =[0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d];
157 |
158 | // Transformations for encryption
159 | var T1 = [0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a];
160 | var T2 = [0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616];
161 | var T3 = [0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16];
162 | var T4 = [0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c];
163 |
164 | // Transformations for decryption
165 | var T5 = [0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742];
166 | var T6 = [0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857];
167 | var T7 = [0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8];
168 | var T8 = [0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0];
169 |
170 | // Transformations for decryption key expansion
171 | var U1 = [0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3];
172 | var U2 = [0x00000000, 0x0b0e090d, 0x161c121a, 0x1d121b17, 0x2c382434, 0x27362d39, 0x3a24362e, 0x312a3f23, 0x58704868, 0x537e4165, 0x4e6c5a72, 0x4562537f, 0x74486c5c, 0x7f466551, 0x62547e46, 0x695a774b, 0xb0e090d0, 0xbbee99dd, 0xa6fc82ca, 0xadf28bc7, 0x9cd8b4e4, 0x97d6bde9, 0x8ac4a6fe, 0x81caaff3, 0xe890d8b8, 0xe39ed1b5, 0xfe8ccaa2, 0xf582c3af, 0xc4a8fc8c, 0xcfa6f581, 0xd2b4ee96, 0xd9bae79b, 0x7bdb3bbb, 0x70d532b6, 0x6dc729a1, 0x66c920ac, 0x57e31f8f, 0x5ced1682, 0x41ff0d95, 0x4af10498, 0x23ab73d3, 0x28a57ade, 0x35b761c9, 0x3eb968c4, 0x0f9357e7, 0x049d5eea, 0x198f45fd, 0x12814cf0, 0xcb3bab6b, 0xc035a266, 0xdd27b971, 0xd629b07c, 0xe7038f5f, 0xec0d8652, 0xf11f9d45, 0xfa119448, 0x934be303, 0x9845ea0e, 0x8557f119, 0x8e59f814, 0xbf73c737, 0xb47dce3a, 0xa96fd52d, 0xa261dc20, 0xf6ad766d, 0xfda37f60, 0xe0b16477, 0xebbf6d7a, 0xda955259, 0xd19b5b54, 0xcc894043, 0xc787494e, 0xaedd3e05, 0xa5d33708, 0xb8c12c1f, 0xb3cf2512, 0x82e51a31, 0x89eb133c, 0x94f9082b, 0x9ff70126, 0x464de6bd, 0x4d43efb0, 0x5051f4a7, 0x5b5ffdaa, 0x6a75c289, 0x617bcb84, 0x7c69d093, 0x7767d99e, 0x1e3daed5, 0x1533a7d8, 0x0821bccf, 0x032fb5c2, 0x32058ae1, 0x390b83ec, 0x241998fb, 0x2f1791f6, 0x8d764dd6, 0x867844db, 0x9b6a5fcc, 0x906456c1, 0xa14e69e2, 0xaa4060ef, 0xb7527bf8, 0xbc5c72f5, 0xd50605be, 0xde080cb3, 0xc31a17a4, 0xc8141ea9, 0xf93e218a, 0xf2302887, 0xef223390, 0xe42c3a9d, 0x3d96dd06, 0x3698d40b, 0x2b8acf1c, 0x2084c611, 0x11aef932, 0x1aa0f03f, 0x07b2eb28, 0x0cbce225, 0x65e6956e, 0x6ee89c63, 0x73fa8774, 0x78f48e79, 0x49deb15a, 0x42d0b857, 0x5fc2a340, 0x54ccaa4d, 0xf741ecda, 0xfc4fe5d7, 0xe15dfec0, 0xea53f7cd, 0xdb79c8ee, 0xd077c1e3, 0xcd65daf4, 0xc66bd3f9, 0xaf31a4b2, 0xa43fadbf, 0xb92db6a8, 0xb223bfa5, 0x83098086, 0x8807898b, 0x9515929c, 0x9e1b9b91, 0x47a17c0a, 0x4caf7507, 0x51bd6e10, 0x5ab3671d, 0x6b99583e, 0x60975133, 0x7d854a24, 0x768b4329, 0x1fd13462, 0x14df3d6f, 0x09cd2678, 0x02c32f75, 0x33e91056, 0x38e7195b, 0x25f5024c, 0x2efb0b41, 0x8c9ad761, 0x8794de6c, 0x9a86c57b, 0x9188cc76, 0xa0a2f355, 0xabacfa58, 0xb6bee14f, 0xbdb0e842, 0xd4ea9f09, 0xdfe49604, 0xc2f68d13, 0xc9f8841e, 0xf8d2bb3d, 0xf3dcb230, 0xeecea927, 0xe5c0a02a, 0x3c7a47b1, 0x37744ebc, 0x2a6655ab, 0x21685ca6, 0x10426385, 0x1b4c6a88, 0x065e719f, 0x0d507892, 0x640a0fd9, 0x6f0406d4, 0x72161dc3, 0x791814ce, 0x48322bed, 0x433c22e0, 0x5e2e39f7, 0x552030fa, 0x01ec9ab7, 0x0ae293ba, 0x17f088ad, 0x1cfe81a0, 0x2dd4be83, 0x26dab78e, 0x3bc8ac99, 0x30c6a594, 0x599cd2df, 0x5292dbd2, 0x4f80c0c5, 0x448ec9c8, 0x75a4f6eb, 0x7eaaffe6, 0x63b8e4f1, 0x68b6edfc, 0xb10c0a67, 0xba02036a, 0xa710187d, 0xac1e1170, 0x9d342e53, 0x963a275e, 0x8b283c49, 0x80263544, 0xe97c420f, 0xe2724b02, 0xff605015, 0xf46e5918, 0xc544663b, 0xce4a6f36, 0xd3587421, 0xd8567d2c, 0x7a37a10c, 0x7139a801, 0x6c2bb316, 0x6725ba1b, 0x560f8538, 0x5d018c35, 0x40139722, 0x4b1d9e2f, 0x2247e964, 0x2949e069, 0x345bfb7e, 0x3f55f273, 0x0e7fcd50, 0x0571c45d, 0x1863df4a, 0x136dd647, 0xcad731dc, 0xc1d938d1, 0xdccb23c6, 0xd7c52acb, 0xe6ef15e8, 0xede11ce5, 0xf0f307f2, 0xfbfd0eff, 0x92a779b4, 0x99a970b9, 0x84bb6bae, 0x8fb562a3, 0xbe9f5d80, 0xb591548d, 0xa8834f9a, 0xa38d4697];
173 | var U3 = [0x00000000, 0x0d0b0e09, 0x1a161c12, 0x171d121b, 0x342c3824, 0x3927362d, 0x2e3a2436, 0x23312a3f, 0x68587048, 0x65537e41, 0x724e6c5a, 0x7f456253, 0x5c74486c, 0x517f4665, 0x4662547e, 0x4b695a77, 0xd0b0e090, 0xddbbee99, 0xcaa6fc82, 0xc7adf28b, 0xe49cd8b4, 0xe997d6bd, 0xfe8ac4a6, 0xf381caaf, 0xb8e890d8, 0xb5e39ed1, 0xa2fe8cca, 0xaff582c3, 0x8cc4a8fc, 0x81cfa6f5, 0x96d2b4ee, 0x9bd9bae7, 0xbb7bdb3b, 0xb670d532, 0xa16dc729, 0xac66c920, 0x8f57e31f, 0x825ced16, 0x9541ff0d, 0x984af104, 0xd323ab73, 0xde28a57a, 0xc935b761, 0xc43eb968, 0xe70f9357, 0xea049d5e, 0xfd198f45, 0xf012814c, 0x6bcb3bab, 0x66c035a2, 0x71dd27b9, 0x7cd629b0, 0x5fe7038f, 0x52ec0d86, 0x45f11f9d, 0x48fa1194, 0x03934be3, 0x0e9845ea, 0x198557f1, 0x148e59f8, 0x37bf73c7, 0x3ab47dce, 0x2da96fd5, 0x20a261dc, 0x6df6ad76, 0x60fda37f, 0x77e0b164, 0x7aebbf6d, 0x59da9552, 0x54d19b5b, 0x43cc8940, 0x4ec78749, 0x05aedd3e, 0x08a5d337, 0x1fb8c12c, 0x12b3cf25, 0x3182e51a, 0x3c89eb13, 0x2b94f908, 0x269ff701, 0xbd464de6, 0xb04d43ef, 0xa75051f4, 0xaa5b5ffd, 0x896a75c2, 0x84617bcb, 0x937c69d0, 0x9e7767d9, 0xd51e3dae, 0xd81533a7, 0xcf0821bc, 0xc2032fb5, 0xe132058a, 0xec390b83, 0xfb241998, 0xf62f1791, 0xd68d764d, 0xdb867844, 0xcc9b6a5f, 0xc1906456, 0xe2a14e69, 0xefaa4060, 0xf8b7527b, 0xf5bc5c72, 0xbed50605, 0xb3de080c, 0xa4c31a17, 0xa9c8141e, 0x8af93e21, 0x87f23028, 0x90ef2233, 0x9de42c3a, 0x063d96dd, 0x0b3698d4, 0x1c2b8acf, 0x112084c6, 0x3211aef9, 0x3f1aa0f0, 0x2807b2eb, 0x250cbce2, 0x6e65e695, 0x636ee89c, 0x7473fa87, 0x7978f48e, 0x5a49deb1, 0x5742d0b8, 0x405fc2a3, 0x4d54ccaa, 0xdaf741ec, 0xd7fc4fe5, 0xc0e15dfe, 0xcdea53f7, 0xeedb79c8, 0xe3d077c1, 0xf4cd65da, 0xf9c66bd3, 0xb2af31a4, 0xbfa43fad, 0xa8b92db6, 0xa5b223bf, 0x86830980, 0x8b880789, 0x9c951592, 0x919e1b9b, 0x0a47a17c, 0x074caf75, 0x1051bd6e, 0x1d5ab367, 0x3e6b9958, 0x33609751, 0x247d854a, 0x29768b43, 0x621fd134, 0x6f14df3d, 0x7809cd26, 0x7502c32f, 0x5633e910, 0x5b38e719, 0x4c25f502, 0x412efb0b, 0x618c9ad7, 0x6c8794de, 0x7b9a86c5, 0x769188cc, 0x55a0a2f3, 0x58abacfa, 0x4fb6bee1, 0x42bdb0e8, 0x09d4ea9f, 0x04dfe496, 0x13c2f68d, 0x1ec9f884, 0x3df8d2bb, 0x30f3dcb2, 0x27eecea9, 0x2ae5c0a0, 0xb13c7a47, 0xbc37744e, 0xab2a6655, 0xa621685c, 0x85104263, 0x881b4c6a, 0x9f065e71, 0x920d5078, 0xd9640a0f, 0xd46f0406, 0xc372161d, 0xce791814, 0xed48322b, 0xe0433c22, 0xf75e2e39, 0xfa552030, 0xb701ec9a, 0xba0ae293, 0xad17f088, 0xa01cfe81, 0x832dd4be, 0x8e26dab7, 0x993bc8ac, 0x9430c6a5, 0xdf599cd2, 0xd25292db, 0xc54f80c0, 0xc8448ec9, 0xeb75a4f6, 0xe67eaaff, 0xf163b8e4, 0xfc68b6ed, 0x67b10c0a, 0x6aba0203, 0x7da71018, 0x70ac1e11, 0x539d342e, 0x5e963a27, 0x498b283c, 0x44802635, 0x0fe97c42, 0x02e2724b, 0x15ff6050, 0x18f46e59, 0x3bc54466, 0x36ce4a6f, 0x21d35874, 0x2cd8567d, 0x0c7a37a1, 0x017139a8, 0x166c2bb3, 0x1b6725ba, 0x38560f85, 0x355d018c, 0x22401397, 0x2f4b1d9e, 0x642247e9, 0x692949e0, 0x7e345bfb, 0x733f55f2, 0x500e7fcd, 0x5d0571c4, 0x4a1863df, 0x47136dd6, 0xdccad731, 0xd1c1d938, 0xc6dccb23, 0xcbd7c52a, 0xe8e6ef15, 0xe5ede11c, 0xf2f0f307, 0xfffbfd0e, 0xb492a779, 0xb999a970, 0xae84bb6b, 0xa38fb562, 0x80be9f5d, 0x8db59154, 0x9aa8834f, 0x97a38d46];
174 | var U4 = [0x00000000, 0x090d0b0e, 0x121a161c, 0x1b171d12, 0x24342c38, 0x2d392736, 0x362e3a24, 0x3f23312a, 0x48685870, 0x4165537e, 0x5a724e6c, 0x537f4562, 0x6c5c7448, 0x65517f46, 0x7e466254, 0x774b695a, 0x90d0b0e0, 0x99ddbbee, 0x82caa6fc, 0x8bc7adf2, 0xb4e49cd8, 0xbde997d6, 0xa6fe8ac4, 0xaff381ca, 0xd8b8e890, 0xd1b5e39e, 0xcaa2fe8c, 0xc3aff582, 0xfc8cc4a8, 0xf581cfa6, 0xee96d2b4, 0xe79bd9ba, 0x3bbb7bdb, 0x32b670d5, 0x29a16dc7, 0x20ac66c9, 0x1f8f57e3, 0x16825ced, 0x0d9541ff, 0x04984af1, 0x73d323ab, 0x7ade28a5, 0x61c935b7, 0x68c43eb9, 0x57e70f93, 0x5eea049d, 0x45fd198f, 0x4cf01281, 0xab6bcb3b, 0xa266c035, 0xb971dd27, 0xb07cd629, 0x8f5fe703, 0x8652ec0d, 0x9d45f11f, 0x9448fa11, 0xe303934b, 0xea0e9845, 0xf1198557, 0xf8148e59, 0xc737bf73, 0xce3ab47d, 0xd52da96f, 0xdc20a261, 0x766df6ad, 0x7f60fda3, 0x6477e0b1, 0x6d7aebbf, 0x5259da95, 0x5b54d19b, 0x4043cc89, 0x494ec787, 0x3e05aedd, 0x3708a5d3, 0x2c1fb8c1, 0x2512b3cf, 0x1a3182e5, 0x133c89eb, 0x082b94f9, 0x01269ff7, 0xe6bd464d, 0xefb04d43, 0xf4a75051, 0xfdaa5b5f, 0xc2896a75, 0xcb84617b, 0xd0937c69, 0xd99e7767, 0xaed51e3d, 0xa7d81533, 0xbccf0821, 0xb5c2032f, 0x8ae13205, 0x83ec390b, 0x98fb2419, 0x91f62f17, 0x4dd68d76, 0x44db8678, 0x5fcc9b6a, 0x56c19064, 0x69e2a14e, 0x60efaa40, 0x7bf8b752, 0x72f5bc5c, 0x05bed506, 0x0cb3de08, 0x17a4c31a, 0x1ea9c814, 0x218af93e, 0x2887f230, 0x3390ef22, 0x3a9de42c, 0xdd063d96, 0xd40b3698, 0xcf1c2b8a, 0xc6112084, 0xf93211ae, 0xf03f1aa0, 0xeb2807b2, 0xe2250cbc, 0x956e65e6, 0x9c636ee8, 0x877473fa, 0x8e7978f4, 0xb15a49de, 0xb85742d0, 0xa3405fc2, 0xaa4d54cc, 0xecdaf741, 0xe5d7fc4f, 0xfec0e15d, 0xf7cdea53, 0xc8eedb79, 0xc1e3d077, 0xdaf4cd65, 0xd3f9c66b, 0xa4b2af31, 0xadbfa43f, 0xb6a8b92d, 0xbfa5b223, 0x80868309, 0x898b8807, 0x929c9515, 0x9b919e1b, 0x7c0a47a1, 0x75074caf, 0x6e1051bd, 0x671d5ab3, 0x583e6b99, 0x51336097, 0x4a247d85, 0x4329768b, 0x34621fd1, 0x3d6f14df, 0x267809cd, 0x2f7502c3, 0x105633e9, 0x195b38e7, 0x024c25f5, 0x0b412efb, 0xd7618c9a, 0xde6c8794, 0xc57b9a86, 0xcc769188, 0xf355a0a2, 0xfa58abac, 0xe14fb6be, 0xe842bdb0, 0x9f09d4ea, 0x9604dfe4, 0x8d13c2f6, 0x841ec9f8, 0xbb3df8d2, 0xb230f3dc, 0xa927eece, 0xa02ae5c0, 0x47b13c7a, 0x4ebc3774, 0x55ab2a66, 0x5ca62168, 0x63851042, 0x6a881b4c, 0x719f065e, 0x78920d50, 0x0fd9640a, 0x06d46f04, 0x1dc37216, 0x14ce7918, 0x2bed4832, 0x22e0433c, 0x39f75e2e, 0x30fa5520, 0x9ab701ec, 0x93ba0ae2, 0x88ad17f0, 0x81a01cfe, 0xbe832dd4, 0xb78e26da, 0xac993bc8, 0xa59430c6, 0xd2df599c, 0xdbd25292, 0xc0c54f80, 0xc9c8448e, 0xf6eb75a4, 0xffe67eaa, 0xe4f163b8, 0xedfc68b6, 0x0a67b10c, 0x036aba02, 0x187da710, 0x1170ac1e, 0x2e539d34, 0x275e963a, 0x3c498b28, 0x35448026, 0x420fe97c, 0x4b02e272, 0x5015ff60, 0x5918f46e, 0x663bc544, 0x6f36ce4a, 0x7421d358, 0x7d2cd856, 0xa10c7a37, 0xa8017139, 0xb3166c2b, 0xba1b6725, 0x8538560f, 0x8c355d01, 0x97224013, 0x9e2f4b1d, 0xe9642247, 0xe0692949, 0xfb7e345b, 0xf2733f55, 0xcd500e7f, 0xc45d0571, 0xdf4a1863, 0xd647136d, 0x31dccad7, 0x38d1c1d9, 0x23c6dccb, 0x2acbd7c5, 0x15e8e6ef, 0x1ce5ede1, 0x07f2f0f3, 0x0efffbfd, 0x79b492a7, 0x70b999a9, 0x6bae84bb, 0x62a38fb5, 0x5d80be9f, 0x548db591, 0x4f9aa883, 0x4697a38d];
175 |
176 | function convertToInt32(bytes) {
177 | var result = [];
178 | for (var i = 0; i < bytes.length; i += 4) {
179 | result.push(
180 | (bytes[i ] << 24) |
181 | (bytes[i + 1] << 16) |
182 | (bytes[i + 2] << 8) |
183 | bytes[i + 3]
184 | );
185 | }
186 | return result;
187 | }
188 |
189 | var AES = function(key) {
190 | if (!(this instanceof AES)) {
191 | throw Error('AES must be instanitated with `new`');
192 | }
193 |
194 | Object.defineProperty(this, 'key', {
195 | value: coerceArray(key, true)
196 | });
197 |
198 | this._prepare();
199 | }
200 |
201 |
202 | AES.prototype._prepare = function() {
203 |
204 | var rounds = numberOfRounds[this.key.length];
205 | if (rounds == null) {
206 | throw new Error('invalid key size (must be 16, 24 or 32 bytes)');
207 | }
208 |
209 | // encryption round keys
210 | this._Ke = [];
211 |
212 | // decryption round keys
213 | this._Kd = [];
214 |
215 | for (var i = 0; i <= rounds; i++) {
216 | this._Ke.push([0, 0, 0, 0]);
217 | this._Kd.push([0, 0, 0, 0]);
218 | }
219 |
220 | var roundKeyCount = (rounds + 1) * 4;
221 | var KC = this.key.length / 4;
222 |
223 | // convert the key into ints
224 | var tk = convertToInt32(this.key);
225 |
226 | // copy values into round key arrays
227 | var index;
228 | for (var i = 0; i < KC; i++) {
229 | index = i >> 2;
230 | this._Ke[index][i % 4] = tk[i];
231 | this._Kd[rounds - index][i % 4] = tk[i];
232 | }
233 |
234 | // key expansion (fips-197 section 5.2)
235 | var rconpointer = 0;
236 | var t = KC, tt;
237 | while (t < roundKeyCount) {
238 | tt = tk[KC - 1];
239 | tk[0] ^= ((S[(tt >> 16) & 0xFF] << 24) ^
240 | (S[(tt >> 8) & 0xFF] << 16) ^
241 | (S[ tt & 0xFF] << 8) ^
242 | S[(tt >> 24) & 0xFF] ^
243 | (rcon[rconpointer] << 24));
244 | rconpointer += 1;
245 |
246 | // key expansion (for non-256 bit)
247 | if (KC != 8) {
248 | for (var i = 1; i < KC; i++) {
249 | tk[i] ^= tk[i - 1];
250 | }
251 |
252 | // key expansion for 256-bit keys is "slightly different" (fips-197)
253 | } else {
254 | for (var i = 1; i < (KC / 2); i++) {
255 | tk[i] ^= tk[i - 1];
256 | }
257 | tt = tk[(KC / 2) - 1];
258 |
259 | tk[KC / 2] ^= (S[ tt & 0xFF] ^
260 | (S[(tt >> 8) & 0xFF] << 8) ^
261 | (S[(tt >> 16) & 0xFF] << 16) ^
262 | (S[(tt >> 24) & 0xFF] << 24));
263 |
264 | for (var i = (KC / 2) + 1; i < KC; i++) {
265 | tk[i] ^= tk[i - 1];
266 | }
267 | }
268 |
269 | // copy values into round key arrays
270 | var i = 0, r, c;
271 | while (i < KC && t < roundKeyCount) {
272 | r = t >> 2;
273 | c = t % 4;
274 | this._Ke[r][c] = tk[i];
275 | this._Kd[rounds - r][c] = tk[i++];
276 | t++;
277 | }
278 | }
279 |
280 | // inverse-cipher-ify the decryption round key (fips-197 section 5.3)
281 | for (var r = 1; r < rounds; r++) {
282 | for (var c = 0; c < 4; c++) {
283 | tt = this._Kd[r][c];
284 | this._Kd[r][c] = (U1[(tt >> 24) & 0xFF] ^
285 | U2[(tt >> 16) & 0xFF] ^
286 | U3[(tt >> 8) & 0xFF] ^
287 | U4[ tt & 0xFF]);
288 | }
289 | }
290 | }
291 |
292 | AES.prototype.encrypt = function(plaintext) {
293 | if (plaintext.length != 16) {
294 | throw new Error('invalid plaintext size (must be 16 bytes)');
295 | }
296 |
297 | var rounds = this._Ke.length - 1;
298 | var a = [0, 0, 0, 0];
299 |
300 | // convert plaintext to (ints ^ key)
301 | var t = convertToInt32(plaintext);
302 | for (var i = 0; i < 4; i++) {
303 | t[i] ^= this._Ke[0][i];
304 | }
305 |
306 | // apply round transforms
307 | for (var r = 1; r < rounds; r++) {
308 | for (var i = 0; i < 4; i++) {
309 | a[i] = (T1[(t[ i ] >> 24) & 0xff] ^
310 | T2[(t[(i + 1) % 4] >> 16) & 0xff] ^
311 | T3[(t[(i + 2) % 4] >> 8) & 0xff] ^
312 | T4[ t[(i + 3) % 4] & 0xff] ^
313 | this._Ke[r][i]);
314 | }
315 | t = a.slice();
316 | }
317 |
318 | // the last round is special
319 | var result = createArray(16), tt;
320 | for (var i = 0; i < 4; i++) {
321 | tt = this._Ke[rounds][i];
322 | result[4 * i ] = (S[(t[ i ] >> 24) & 0xff] ^ (tt >> 24)) & 0xff;
323 | result[4 * i + 1] = (S[(t[(i + 1) % 4] >> 16) & 0xff] ^ (tt >> 16)) & 0xff;
324 | result[4 * i + 2] = (S[(t[(i + 2) % 4] >> 8) & 0xff] ^ (tt >> 8)) & 0xff;
325 | result[4 * i + 3] = (S[ t[(i + 3) % 4] & 0xff] ^ tt ) & 0xff;
326 | }
327 |
328 | return result;
329 | }
330 |
331 | AES.prototype.decrypt = function(ciphertext) {
332 | if (ciphertext.length != 16) {
333 | throw new Error('invalid ciphertext size (must be 16 bytes)');
334 | }
335 |
336 | var rounds = this._Kd.length - 1;
337 | var a = [0, 0, 0, 0];
338 |
339 | // convert plaintext to (ints ^ key)
340 | var t = convertToInt32(ciphertext);
341 | for (var i = 0; i < 4; i++) {
342 | t[i] ^= this._Kd[0][i];
343 | }
344 |
345 | // apply round transforms
346 | for (var r = 1; r < rounds; r++) {
347 | for (var i = 0; i < 4; i++) {
348 | a[i] = (T5[(t[ i ] >> 24) & 0xff] ^
349 | T6[(t[(i + 3) % 4] >> 16) & 0xff] ^
350 | T7[(t[(i + 2) % 4] >> 8) & 0xff] ^
351 | T8[ t[(i + 1) % 4] & 0xff] ^
352 | this._Kd[r][i]);
353 | }
354 | t = a.slice();
355 | }
356 |
357 | // the last round is special
358 | var result = createArray(16), tt;
359 | for (var i = 0; i < 4; i++) {
360 | tt = this._Kd[rounds][i];
361 | result[4 * i ] = (Si[(t[ i ] >> 24) & 0xff] ^ (tt >> 24)) & 0xff;
362 | result[4 * i + 1] = (Si[(t[(i + 3) % 4] >> 16) & 0xff] ^ (tt >> 16)) & 0xff;
363 | result[4 * i + 2] = (Si[(t[(i + 2) % 4] >> 8) & 0xff] ^ (tt >> 8)) & 0xff;
364 | result[4 * i + 3] = (Si[ t[(i + 1) % 4] & 0xff] ^ tt ) & 0xff;
365 | }
366 |
367 | return result;
368 | }
369 |
370 |
371 | /**
372 | * Mode Of Operation - Electonic Codebook (ECB)
373 | */
374 | var ModeOfOperationECB = function(key) {
375 | if (!(this instanceof ModeOfOperationECB)) {
376 | throw Error('AES must be instanitated with `new`');
377 | }
378 |
379 | this.description = "Electronic Code Block";
380 | this.name = "ecb";
381 |
382 | this._aes = new AES(key);
383 | }
384 |
385 | ModeOfOperationECB.prototype.encrypt = function(plaintext) {
386 | plaintext = coerceArray(plaintext);
387 |
388 | if ((plaintext.length % 16) !== 0) {
389 | throw new Error('invalid plaintext size (must be multiple of 16 bytes)');
390 | }
391 |
392 | var ciphertext = createArray(plaintext.length);
393 | var block = createArray(16);
394 |
395 | for (var i = 0; i < plaintext.length; i += 16) {
396 | copyArray(plaintext, block, 0, i, i + 16);
397 | block = this._aes.encrypt(block);
398 | copyArray(block, ciphertext, i);
399 | }
400 |
401 | return ciphertext;
402 | }
403 |
404 | ModeOfOperationECB.prototype.decrypt = function(ciphertext) {
405 | ciphertext = coerceArray(ciphertext);
406 |
407 | if ((ciphertext.length % 16) !== 0) {
408 | throw new Error('invalid ciphertext size (must be multiple of 16 bytes)');
409 | }
410 |
411 | var plaintext = createArray(ciphertext.length);
412 | var block = createArray(16);
413 |
414 | for (var i = 0; i < ciphertext.length; i += 16) {
415 | copyArray(ciphertext, block, 0, i, i + 16);
416 | block = this._aes.decrypt(block);
417 | copyArray(block, plaintext, i);
418 | }
419 |
420 | return plaintext;
421 | }
422 |
423 |
424 | /**
425 | * Mode Of Operation - Cipher Block Chaining (CBC)
426 | */
427 | var ModeOfOperationCBC = function(key, iv) {
428 | if (!(this instanceof ModeOfOperationCBC)) {
429 | throw Error('AES must be instanitated with `new`');
430 | }
431 |
432 | this.description = "Cipher Block Chaining";
433 | this.name = "cbc";
434 |
435 | if (!iv) {
436 | iv = createArray(16);
437 |
438 | } else if (iv.length != 16) {
439 | throw new Error('invalid initialation vector size (must be 16 bytes)');
440 | }
441 |
442 | this._lastCipherblock = coerceArray(iv, true);
443 |
444 | this._aes = new AES(key);
445 | }
446 |
447 | ModeOfOperationCBC.prototype.encrypt = function(plaintext) {
448 | plaintext = coerceArray(plaintext);
449 |
450 | if ((plaintext.length % 16) !== 0) {
451 | throw new Error('invalid plaintext size (must be multiple of 16 bytes)');
452 | }
453 |
454 | var ciphertext = createArray(plaintext.length);
455 | var block = createArray(16);
456 |
457 | for (var i = 0; i < plaintext.length; i += 16) {
458 | copyArray(plaintext, block, 0, i, i + 16);
459 |
460 | for (var j = 0; j < 16; j++) {
461 | block[j] ^= this._lastCipherblock[j];
462 | }
463 |
464 | this._lastCipherblock = this._aes.encrypt(block);
465 | copyArray(this._lastCipherblock, ciphertext, i);
466 | }
467 |
468 | return ciphertext;
469 | }
470 |
471 | ModeOfOperationCBC.prototype.decrypt = function(ciphertext) {
472 | ciphertext = coerceArray(ciphertext);
473 |
474 | if ((ciphertext.length % 16) !== 0) {
475 | throw new Error('invalid ciphertext size (must be multiple of 16 bytes)');
476 | }
477 |
478 | var plaintext = createArray(ciphertext.length);
479 | var block = createArray(16);
480 |
481 | for (var i = 0; i < ciphertext.length; i += 16) {
482 | copyArray(ciphertext, block, 0, i, i + 16);
483 | block = this._aes.decrypt(block);
484 |
485 | for (var j = 0; j < 16; j++) {
486 | plaintext[i + j] = block[j] ^ this._lastCipherblock[j];
487 | }
488 |
489 | copyArray(ciphertext, this._lastCipherblock, 0, i, i + 16);
490 | }
491 |
492 | return plaintext;
493 | }
494 |
495 |
496 | /**
497 | * Mode Of Operation - Cipher Feedback (CFB)
498 | */
499 | var ModeOfOperationCFB = function(key, iv, segmentSize) {
500 | if (!(this instanceof ModeOfOperationCFB)) {
501 | throw Error('AES must be instanitated with `new`');
502 | }
503 |
504 | this.description = "Cipher Feedback";
505 | this.name = "cfb";
506 |
507 | if (!iv) {
508 | iv = createArray(16);
509 |
510 | } else if (iv.length != 16) {
511 | throw new Error('invalid initialation vector size (must be 16 size)');
512 | }
513 |
514 | if (!segmentSize) { segmentSize = 1; }
515 |
516 | this.segmentSize = segmentSize;
517 |
518 | this._shiftRegister = coerceArray(iv, true);
519 |
520 | this._aes = new AES(key);
521 | }
522 |
523 | ModeOfOperationCFB.prototype.encrypt = function(plaintext) {
524 | if ((plaintext.length % this.segmentSize) != 0) {
525 | throw new Error('invalid plaintext size (must be segmentSize bytes)');
526 | }
527 |
528 | var encrypted = coerceArray(plaintext, true);
529 |
530 | var xorSegment;
531 | for (var i = 0; i < encrypted.length; i += this.segmentSize) {
532 | xorSegment = this._aes.encrypt(this._shiftRegister);
533 | for (var j = 0; j < this.segmentSize; j++) {
534 | encrypted[i + j] ^= xorSegment[j];
535 | }
536 |
537 | // Shift the register
538 | copyArray(this._shiftRegister, this._shiftRegister, 0, this.segmentSize);
539 | copyArray(encrypted, this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize);
540 | }
541 |
542 | return encrypted;
543 | }
544 |
545 | ModeOfOperationCFB.prototype.decrypt = function(ciphertext) {
546 | if ((ciphertext.length % this.segmentSize) != 0) {
547 | throw new Error('invalid ciphertext size (must be segmentSize bytes)');
548 | }
549 |
550 | var plaintext = coerceArray(ciphertext, true);
551 |
552 | var xorSegment;
553 | for (var i = 0; i < plaintext.length; i += this.segmentSize) {
554 | xorSegment = this._aes.encrypt(this._shiftRegister);
555 |
556 | for (var j = 0; j < this.segmentSize; j++) {
557 | plaintext[i + j] ^= xorSegment[j];
558 | }
559 |
560 | // Shift the register
561 | copyArray(this._shiftRegister, this._shiftRegister, 0, this.segmentSize);
562 | copyArray(ciphertext, this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize);
563 | }
564 |
565 | return plaintext;
566 | }
567 |
568 | /**
569 | * Mode Of Operation - Output Feedback (OFB)
570 | */
571 | var ModeOfOperationOFB = function(key, iv) {
572 | if (!(this instanceof ModeOfOperationOFB)) {
573 | throw Error('AES must be instanitated with `new`');
574 | }
575 |
576 | this.description = "Output Feedback";
577 | this.name = "ofb";
578 |
579 | if (!iv) {
580 | iv = createArray(16);
581 |
582 | } else if (iv.length != 16) {
583 | throw new Error('invalid initialation vector size (must be 16 bytes)');
584 | }
585 |
586 | this._lastPrecipher = coerceArray(iv, true);
587 | this._lastPrecipherIndex = 16;
588 |
589 | this._aes = new AES(key);
590 | }
591 |
592 | ModeOfOperationOFB.prototype.encrypt = function(plaintext) {
593 | var encrypted = coerceArray(plaintext, true);
594 |
595 | for (var i = 0; i < encrypted.length; i++) {
596 | if (this._lastPrecipherIndex === 16) {
597 | this._lastPrecipher = this._aes.encrypt(this._lastPrecipher);
598 | this._lastPrecipherIndex = 0;
599 | }
600 | encrypted[i] ^= this._lastPrecipher[this._lastPrecipherIndex++];
601 | }
602 |
603 | return encrypted;
604 | }
605 |
606 | // Decryption is symetric
607 | ModeOfOperationOFB.prototype.decrypt = ModeOfOperationOFB.prototype.encrypt;
608 |
609 |
610 | /**
611 | * Counter object for CTR common mode of operation
612 | */
613 | var Counter = function(initialValue) {
614 | if (!(this instanceof Counter)) {
615 | throw Error('Counter must be instanitated with `new`');
616 | }
617 |
618 | // We allow 0, but anything false-ish uses the default 1
619 | if (initialValue !== 0 && !initialValue) { initialValue = 1; }
620 |
621 | if (typeof(initialValue) === 'number') {
622 | this._counter = createArray(16);
623 | this.setValue(initialValue);
624 |
625 | } else {
626 | this.setBytes(initialValue);
627 | }
628 | }
629 |
630 | Counter.prototype.setValue = function(value) {
631 | if (typeof(value) !== 'number' || parseInt(value) != value) {
632 | throw new Error('invalid counter value (must be an integer)');
633 | }
634 |
635 | // We cannot safely handle numbers beyond the safe range for integers
636 | if (value > Number.MAX_SAFE_INTEGER) {
637 | throw new Error('integer value out of safe range');
638 | }
639 |
640 | for (var index = 15; index >= 0; --index) {
641 | this._counter[index] = value % 256;
642 | value = parseInt(value / 256);
643 | }
644 | }
645 |
646 | Counter.prototype.setBytes = function(bytes) {
647 | bytes = coerceArray(bytes, true);
648 |
649 | if (bytes.length != 16) {
650 | throw new Error('invalid counter bytes size (must be 16 bytes)');
651 | }
652 |
653 | this._counter = bytes;
654 | };
655 |
656 | Counter.prototype.increment = function() {
657 | for (var i = 15; i >= 0; i--) {
658 | if (this._counter[i] === 255) {
659 | this._counter[i] = 0;
660 | } else {
661 | this._counter[i]++;
662 | break;
663 | }
664 | }
665 | }
666 |
667 |
668 | /**
669 | * Mode Of Operation - Counter (CTR)
670 | */
671 | var ModeOfOperationCTR = function(key, counter) {
672 | if (!(this instanceof ModeOfOperationCTR)) {
673 | throw Error('AES must be instanitated with `new`');
674 | }
675 |
676 | this.description = "Counter";
677 | this.name = "ctr";
678 |
679 | if (!(counter instanceof Counter)) {
680 | counter = new Counter(counter)
681 | }
682 |
683 | this._counter = counter;
684 |
685 | this._remainingCounter = null;
686 | this._remainingCounterIndex = 16;
687 |
688 | this._aes = new AES(key);
689 | }
690 |
691 | ModeOfOperationCTR.prototype.encrypt = function(plaintext) {
692 | var encrypted = coerceArray(plaintext, true);
693 |
694 | for (var i = 0; i < encrypted.length; i++) {
695 | if (this._remainingCounterIndex === 16) {
696 | this._remainingCounter = this._aes.encrypt(this._counter._counter);
697 | this._remainingCounterIndex = 0;
698 | this._counter.increment();
699 | }
700 | encrypted[i] ^= this._remainingCounter[this._remainingCounterIndex++];
701 | }
702 |
703 | return encrypted;
704 | }
705 |
706 | // Decryption is symetric
707 | ModeOfOperationCTR.prototype.decrypt = ModeOfOperationCTR.prototype.encrypt;
708 |
709 |
710 | ///////////////////////
711 | // Padding
712 |
713 | // See:https://tools.ietf.org/html/rfc2315
714 | function pkcs7pad(data) {
715 | data = coerceArray(data, true);
716 | var padder = 16 - (data.length % 16);
717 | var result = createArray(data.length + padder);
718 | copyArray(data, result);
719 | for (var i = data.length; i < result.length; i++) {
720 | result[i] = padder;
721 | }
722 | return result;
723 | }
724 |
725 | function pkcs7strip(data) {
726 | data = coerceArray(data, true);
727 | if (data.length < 16) { throw new Error('PKCS#7 invalid length'); }
728 |
729 | var padder = data[data.length - 1];
730 | if (padder > 16) { throw new Error('PKCS#7 padding byte out of range'); }
731 |
732 | var length = data.length - padder;
733 | for (var i = 0; i < padder; i++) {
734 | if (data[length + i] !== padder) {
735 | throw new Error('PKCS#7 invalid padding byte');
736 | }
737 | }
738 |
739 | var result = createArray(length);
740 | copyArray(data, result, 0, 0, length);
741 | return result;
742 | }
743 |
744 | ///////////////////////
745 | // Exporting
746 |
747 |
748 | // The block cipher
749 | var aesjs = {
750 | AES: AES,
751 | Counter: Counter,
752 |
753 | ModeOfOperation: {
754 | ecb: ModeOfOperationECB,
755 | cbc: ModeOfOperationCBC,
756 | cfb: ModeOfOperationCFB,
757 | ofb: ModeOfOperationOFB,
758 | ctr: ModeOfOperationCTR
759 | },
760 |
761 | utils: {
762 | hex: convertHex,
763 | utf8: convertUtf8
764 | },
765 |
766 | padding: {
767 | pkcs7: {
768 | pad: pkcs7pad,
769 | strip: pkcs7strip
770 | }
771 | },
772 |
773 | _arrayTest: {
774 | coerceArray: coerceArray,
775 | createArray: createArray,
776 | copyArray: copyArray,
777 | }
778 | };
779 |
780 |
781 | // node.js
782 | if (typeof exports !== 'undefined') {
783 | module.exports = aesjs
784 |
785 | // RequireJS/AMD
786 | // http://www.requirejs.org/docs/api.html
787 | // https://github.com/amdjs/amdjs-api/wiki/AMD
788 | } else if (typeof(define) === 'function' && define.amd) {
789 | define([], function() { return aesjs; });
790 |
791 | // Web Browsers
792 | } else {
793 |
794 | // If there was an existing library at "aesjs" make sure it's still available
795 | if (root.aesjs) {
796 | aesjs._aesjs = root.aesjs;
797 | }
798 |
799 | root.aesjs = aesjs;
800 | }
801 |
802 |
803 | })(this);
804 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "aes-js",
3 | "version": "3.1.2",
4 | "bugs": {
5 | "url": "http://github.com/ricmoo/aes-js/issues",
6 | "email": "github@ricmoo.com"
7 | },
8 | "description": "A pure JavaScript implementation of the AES block cipher and all common modes of operation.",
9 | "devDependencies": {
10 | "nodeunit": "^0.9.1"
11 | },
12 | "main": "index.js",
13 | "scripts": {
14 | "test": "./node_modules/.bin/nodeunit test/index.js"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "git://github.com/ricmoo/aes-js.git"
19 | },
20 | "keywords": [
21 | "aes",
22 | "aes-ctr",
23 | "aes-ofb",
24 | "aes-ecb",
25 | "aes-cbc",
26 | "aes-cfb",
27 | "encrypt",
28 | "decrypt",
29 | "block",
30 | "cipher"
31 | ],
32 | "author": "Richard Moore ",
33 | "license": "MIT"
34 | }
35 |
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 |
2 | function populateTests(tests) {
3 | for (var key in tests) {
4 | module.exports[key] = tests[key];
5 | }
6 | }
7 |
8 | populateTests(require('./test-aes.js'));
9 | populateTests(require('./test-counter.js'));
10 | populateTests(require('./test-buffer.js'));
11 | populateTests(require('./test-errors.js'));
12 | populateTests(require('./test-padding.js'));
13 |
--------------------------------------------------------------------------------
/test/test-aes.js:
--------------------------------------------------------------------------------
1 | var nodeunit = require('nodeunit');
2 |
3 | var aes = require('../index');
4 |
5 | function bufferEquals(a, b) {
6 | if (a.length != b.length) { return false; }
7 | for (var i = 0; i < a.length; i++) {
8 | if (a[i] != b[i]) { return false; }
9 | }
10 | return true;
11 | }
12 |
13 | function makeTest(options) {
14 |
15 | var modeOfOperation = options.modeOfOperation;
16 | var mo = aes.ModeOfOperation[modeOfOperation];
17 |
18 | var plaintext = [];
19 | for (var i = 0; i < options.plaintext.length; i++) {
20 | plaintext.push(Buffer.from(options.plaintext[i]));
21 | }
22 |
23 | var key = Buffer.from(options.key);
24 |
25 | var iv = null;
26 | if (options.iv) { iv = Buffer.from(options.iv); }
27 |
28 | var segmentSize = 0;
29 | if (options.segmentSize) { segmentSize = options.segmentSize; }
30 |
31 | var ciphertext = [];
32 | for (var i = 0; i < options.encrypted.length; i++) {
33 | ciphertext.push(Buffer.from(options.encrypted[i]));
34 | }
35 |
36 |
37 | return function (test) {
38 | var func;
39 | switch (modeOfOperation) {
40 | case 'ecb':
41 | func = function() { return new mo(key); }
42 | break;
43 | case 'cfb':
44 | func = function() { return new mo(key, iv, segmentSize); }
45 | break;
46 | case 'ofb':
47 | case 'cbc':
48 | func = function() { return new mo(key, iv); }
49 | break;
50 | case 'ctr':
51 | func = function() { return new mo(key, new aes.Counter(0)); }
52 | break;
53 | default:
54 | throw new Error('unknwon mode of operation')
55 | }
56 |
57 | var encrypter = func(), decrypter = func();
58 | var totalDiffers = 0;
59 | for (var i = 0; i < plaintext.length; i++) {
60 | var ciphertext2 = encrypter.encrypt(plaintext[i]);
61 | test.ok(bufferEquals(ciphertext2, ciphertext[i]), "encrypt failed to match test vector");
62 |
63 | var plaintext2 = decrypter.decrypt(ciphertext2);
64 | test.ok(bufferEquals(plaintext2, plaintext[i]), "decrypt failed to match original text");
65 | }
66 |
67 | test.done();
68 | };
69 | };
70 |
71 |
72 | var testVectors = require('./test-vectors.json');
73 |
74 | var Tests = {};
75 | var counts = {}
76 | for (var i = 0; i < testVectors.length; i++) {
77 | var test = testVectors[i];
78 | name = test.modeOfOperation + '-' + test.key.length;
79 | counts[name] = (counts[name] || 0) + 1;
80 | Tests['test-' + name + '-' + counts[name]] = makeTest(test);
81 | }
82 |
83 | module.exports = Tests;
84 |
--------------------------------------------------------------------------------
/test/test-buffer.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var nodeunit = require('nodeunit');
4 |
5 | var slowCreateBuffer = require('../index')._arrayTest.coerceArray;
6 |
7 | var testArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
8 | var testBuffer = Buffer.from(testArray);
9 |
10 | // We mimic some weird non-array-but-sortof-like-an-array object that people on
11 | // obscure browsers seem to have problems with, for the purpose of testing our
12 | // slowCreateBuffer.
13 | function WeirdBuffer(data) {
14 | this.length = data.length;
15 | for (var i = 0; i < data.length; i++) {
16 | this[i] = data[i];
17 | }
18 | }
19 |
20 | function buffersEqual(a, b) {
21 | if (a.length !== b.length) { return false; }
22 | for (var i = 0; i < a.length; i++) {
23 | if (a[i] !== b[i]) {
24 | return false;
25 | }
26 | }
27 | return true;
28 | }
29 |
30 | module.exports = {
31 | "test-slowCreate": function(test) {
32 | //var result = new AES(testArray).key;
33 | var result = slowCreateBuffer(testArray);
34 | test.ok(buffersEqual(testArray, result), 'bufferCreate failed to match input array');
35 |
36 | result = slowCreateBuffer(testBuffer);
37 | test.ok(buffersEqual(testBuffer, result), 'bufferCreate failed to match input array');
38 |
39 | result = slowCreateBuffer(new WeirdBuffer(testArray));
40 | test.ok(buffersEqual(testBuffer, result), 'bufferCreate failed to match input array');
41 |
42 | test.done();
43 | },
44 | };
45 |
--------------------------------------------------------------------------------
/test/test-counter.js:
--------------------------------------------------------------------------------
1 | var nodeunit = require('nodeunit');
2 |
3 | var aes = require('../index');
4 |
5 | function bufferEquals(a, b) {
6 | if (a.length != b.length) { return false; }
7 | for (var i = 0; i < a.length; i++) {
8 | if (a[i] != b[i]) { return false; }
9 | }
10 | return true;
11 | }
12 |
13 | function makeTest (options) {
14 | return function(test) {
15 | var result = Buffer.from(options.incrementResult, 'hex');
16 |
17 | if (options.hasOwnProperty('nullish')) {
18 | var counter = new aes.Counter(options.nullish);
19 | counter.increment();
20 | test.ok(bufferEquals(counter._counter, result), "counter failed to initialize with a nullish thing")
21 | }
22 |
23 | if (options.hasOwnProperty('number')) {
24 |
25 | var counter = new aes.Counter(options.number);
26 | counter.increment();
27 | test.ok(bufferEquals(counter._counter, result), "counter failed to initialize with a number")
28 |
29 | counter.setValue(options.number);
30 | counter.increment();
31 | test.ok(bufferEquals(counter._counter, result), "counter failed to reset to a number")
32 |
33 | counter = new aes.Counter();
34 | counter.setValue(options.number);
35 | counter.increment();
36 | test.ok(bufferEquals(counter._counter, result), "counter failed to reset to a number")
37 | }
38 |
39 | if (options.bytes) {
40 | var bytes = Buffer.from(options.bytes, 'hex');
41 |
42 | var counter = new aes.Counter(bytes);
43 | counter.increment();
44 | test.ok(bufferEquals(counter._counter, result), "counter failed to initialize with bytes")
45 |
46 | counter.setBytes(bytes);
47 | counter.increment();
48 | test.ok(bufferEquals(counter._counter, result), "counter failed to reset with bytes")
49 |
50 | counter = new aes.Counter();
51 | counter.setBytes(bytes);
52 | counter.increment();
53 | test.ok(bufferEquals(counter._counter, result), "counter failed to reset with bytes")
54 | }
55 |
56 | test.done();
57 | };
58 | }
59 |
60 | module.exports = {
61 | 'test-counter-nullish-null': makeTest({nullish: null, incrementResult: "00000000000000000000000000000002"}),
62 | 'test-counter-nullish-undefined': makeTest({nullish: undefined, incrementResult: "00000000000000000000000000000002"}),
63 | 'test-counter-number-0': makeTest({number: 0, incrementResult: "00000000000000000000000000000001"}),
64 | 'test-counter-number-1': makeTest({number: 1, incrementResult: "00000000000000000000000000000002"}),
65 | 'test-counter-number-254': makeTest({number: 254, incrementResult: "000000000000000000000000000000ff"}),
66 | 'test-counter-number-255': makeTest({number: 255, incrementResult: "00000000000000000000000000000100"}),
67 | 'test-counter-number-256': makeTest({number: 256, incrementResult: "00000000000000000000000000000101"}),
68 | 'test-counter-number-large': makeTest({number: 1099511627774, incrementResult: "0000000000000000000000ffffffffff"}),
69 | 'test-counter-number-max': makeTest({number: 9007199254740991, incrementResult: "00000000000000000020000000000000"}),
70 | 'test-counter-bytes-0000': makeTest({bytes: "00000000000000000000000000000000", incrementResult: "00000000000000000000000000000001"}),
71 | 'test-counter-bytes-00ff': makeTest({bytes: "000000000000000000000000000000ff", incrementResult: "00000000000000000000000000000100"}),
72 | 'test-counter-bytes-ffff': makeTest({bytes: "ffffffffffffffffffffffffffffffff", incrementResult: "00000000000000000000000000000000"}),
73 | 'test-counter-bytes-dead': makeTest({bytes: "deadbeefdeadbeefdeadbeefdeadbeef", incrementResult: "deadbeefdeadbeefdeadbeefdeadbef0"}),
74 | };
75 |
76 |
--------------------------------------------------------------------------------
/test/test-errors.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var nodeunit = require('nodeunit');
4 |
5 | var aes = require('../index');
6 |
7 | function newBuffer(length) {
8 | var buffer = Buffer.alloc(length);
9 | buffer.fill(42);
10 | return buffer;
11 | }
12 |
13 | // Invalid key sizes to try
14 | var keySizes = [0, 1, 2, 7, 8, 9, 15, 17, 23, 25, 31, 33, 100];
15 |
16 | module.exports = {
17 | "test-errors-key-size": function(test) {
18 | for (var i = 0; i < keySizes.length; i++) {
19 | test.throws(function() {
20 | var moo = new aes.ModeOfOperation.ecb(newBuffer(keySizes[i]));
21 | }, function(error) {
22 | return (error.message === 'invalid key size (must be 16, 24 or 32 bytes)');
23 | },
24 | 'invalid key size failed to throw an error');
25 | }
26 |
27 | test.done();
28 | },
29 |
30 | "test-errors-iv-size": function(test) {
31 | var ivSizes = [0, 15, 17, 100];
32 | for (var i = 0; i < 3; i++) {
33 | var keySize = 16 + i * 8;
34 |
35 | for (var j = 0; j < ivSizes.length; j++) {
36 | test.throws(function() {
37 | var moo = new aes.ModeOfOperation.cbc(newBuffer(keySize), newBuffer(ivSizes[j]));
38 | }, function(error) {
39 | return (error.message === 'invalid initialation vector size (must be 16 bytes)');
40 | },
41 | 'invalid iv size for cbc failed to throw an error');
42 |
43 | test.throws(function() {
44 | var moo = new aes.ModeOfOperation.ofb(newBuffer(keySize), newBuffer(ivSizes[j]));
45 | }, function(error) {
46 | return (error.message === 'invalid initialation vector size (must be 16 bytes)');
47 | },
48 | 'invalid iv size for ofb failed to throw an error');
49 | }
50 | }
51 |
52 | test.done();
53 | },
54 |
55 | "test-errors-segment-size": function(test) {
56 | var key = newBuffer(16);
57 | var iv = newBuffer(16);
58 | for (var i = 1; i < 17; i++) {
59 | for (var j = 1; j < 17; j++) {
60 | if ((j % i) === 0) { continue; }
61 |
62 | var moo = new aes.ModeOfOperation.cfb(key, iv, i);
63 |
64 | test.throws(function() {
65 | moo.encrypt(newBuffer(j));
66 | }, function(error) {
67 | return (error.message === 'invalid plaintext size (must be segmentSize bytes)');
68 | },
69 | 'invalid plaintext (invalid segment size) failed to throw an error ' + i + ' ' + j);
70 | }
71 | }
72 |
73 | test.done();
74 | },
75 |
76 | "test-errors-text-size": function(test) {
77 | var textSizes = [1, 2, 15, 17, 31, 33];
78 |
79 | for (var i = 0; i < 3; i++) {
80 | var key = newBuffer(16 + i * 8);
81 | for (var j = 0; j < textSizes.length; j++) {
82 | for (var k = 0; k < 2; k++) {
83 | var text = newBuffer(textSizes[j]);
84 | if (k === 0) {
85 | var moo = new aes.ModeOfOperation.ecb(key);
86 | } else {
87 | var moo = new aes.ModeOfOperation.cbc(key, newBuffer(16));
88 | }
89 |
90 | test.throws(function() {
91 | moo.encrypt(text);
92 | }, function(error) {
93 | return (error.message === 'invalid plaintext size (must be multiple of 16 bytes)');
94 | },
95 | 'invalid text size failed to throw an error');
96 | }
97 | }
98 | }
99 |
100 | for (var i = 0; i < 3; i++) {
101 | var key = newBuffer(16 + i * 8);
102 | for (var j = 0; j < textSizes.length; j++) {
103 | for (var k = 0; k < 2; k++) {
104 | var text = newBuffer(textSizes[j]);
105 | if (k === 0) {
106 | var moo = new aes.ModeOfOperation.ecb(key);
107 | } else {
108 | var moo = new aes.ModeOfOperation.cbc(key, newBuffer(16));
109 | }
110 |
111 | test.throws(function() {
112 | moo.decrypt(text);
113 | }, function(error) {
114 | return (error.message === 'invalid ciphertext size (must be multiple of 16 bytes)');
115 | },
116 | 'invalid text size failed to throw an error');
117 | }
118 | }
119 | }
120 |
121 | test.done();
122 | },
123 |
124 | "test-errors-counter": function(test) {
125 | var textSizes = [0, 1, 2, 15, 17];
126 | for (var i = 0; i < textSizes.length; i++) {
127 | test.throws(function() {
128 | var counter = new aes.Counter(newBuffer(textSizes[i]));
129 | }, function(error) {
130 | return (error.message === 'invalid counter bytes size (must be 16 bytes)');
131 | },
132 | 'invalid counter size (bytes.length != 16) failed to throw an error');
133 |
134 | var counter = new aes.Counter();
135 | test.throws(function() {
136 | counter.setBytes(newBuffer(textSizes[i]));
137 | }, function(error) {
138 | return (error.message === 'invalid counter bytes size (must be 16 bytes)');
139 | },
140 | 'invalid counter setBytes (bytes.length != 16) failed to throw an error');
141 |
142 | var counter = new aes.Counter();
143 | test.throws(function() {
144 | counter.setValue(newBuffer(textSizes[i]));
145 | }, function(error) {
146 | return (error.message === 'invalid counter value (must be an integer)');
147 | },
148 | 'invalid counter setValue (Array) failed to throw an error');
149 | }
150 |
151 | test.throws(function() {
152 | var counter = new aes.Counter(1.5);
153 | }, function(error) {
154 | return (error.message === 'invalid counter value (must be an integer)');
155 | },
156 | 'invalid counter value (non-integer number) failed to throw an error');
157 |
158 | var counter = new aes.Counter();
159 | test.throws(function() {
160 | counter.setValue(1.5);
161 | }, function(error) {
162 | return (error.message === 'invalid counter value (must be an integer)');
163 | },
164 | 'invalid counter setValue (non-integer number) failed to throw an error');
165 |
166 | test.throws(function() {
167 | var counter = new aes.Counter(Number.MAX_SAFE_INTEGER + 1);
168 | }, function(error) {
169 | return (error.message === 'integer value out of safe range');
170 | },
171 | 'invalid counter value (out of range) failed to throw an error');
172 |
173 | var badThings = [0, 1.5, 1];
174 | for (var i = 0; i < badThings.length; i++) {
175 | var counter = new aes.Counter();
176 | test.throws(function() {
177 | counter.setBytes(badThings[i]);
178 | }, function(error) {
179 | return (error.message === 'unsupported array-like object');
180 | },
181 | 'invalid counter setBytes (numbers) failed to throw an error');
182 | }
183 |
184 | var badThings = [1.5, 'foobar', {}];
185 | for (var i = 0; i < badThings.length; i++) {
186 | var counter = new aes.Counter();
187 | test.throws(function() {
188 | counter.setBytes(badThings[i]);
189 | }, function(error) {
190 | return (error.message === 'unsupported array-like object');
191 | },
192 | 'invalid counter setBytes (' + badThings[i] + ') failed to throw an error');
193 |
194 | var counter = new aes.Counter();
195 | test.throws(function() {
196 | counter.setValue(badThings[i]);
197 | }, function(error) {
198 | return (error.message === 'invalid counter value (must be an integer)');
199 | },
200 | 'invalid counter setValue (' + badThings[i] + ') failed to throw an error');
201 | }
202 |
203 | test.done();
204 | },
205 | };
206 |
--------------------------------------------------------------------------------
/test/test-padding.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var nodeunit = require('nodeunit');
4 |
5 | var aes = require('../index.js');
6 |
7 | function bufferEqual(a, b) {
8 | if (a.length != b.length) { return false; }
9 | for (var i = 0; i < a.length; i++) {
10 | if (a[i] !== b[i]) { return false; }
11 | }
12 | return true;
13 | }
14 |
15 | module.exports = {
16 | "test-padding": function(test) {
17 | for (var size = 0; size < 100; size++) {
18 |
19 | // Create a random piece of data
20 | var data = [];
21 | for (var i = 0; i < size; i++) { data.push(42); }
22 |
23 | // Pad it
24 | var padded = aes.padding.pkcs7.pad(data);
25 | test.ok((padded.length % 16) === 0, "Failed to pad to block size");
26 | test.ok(data.length <= padded.length && padded.length <= data.length + 16, "Padding went awry");
27 | test.ok(padded[padded.length - 1] >= 1 && padded[padded.length - 1] <= 16, "Failed to pad to block size");
28 |
29 | // Trim it
30 | var trimmed = aes.padding.pkcs7.strip(padded);
31 | test.ok(bufferEqual(data, trimmed), "Failed to trim to original data");
32 | }
33 | test.done();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/test/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
103 |
104 |
105 |
--------------------------------------------------------------------------------