996fe143 by brandonocasey

moved ntoh, decrypt, and Decrypter into the same file

1 parent 8cf9c6e1
1 import Stream from '../stream'; 1 import Stream from '../stream';
2 2
3 /**
4 * A wrapper around the Stream class to use setTiemout
5 * and run stream "jobs" Asynchronously
6 */
3 export default class AsyncStream extends Stream { 7 export default class AsyncStream extends Stream {
4 constructor() { 8 constructor() {
5 super(Stream); 9 super(Stream);
......
1 import ntoh from './ntoh';
2 import AES from './aes';
3
4 /* eslint-disable max-len */
5 /**
6 * Decrypt bytes using AES-128 with CBC and PKCS#7 padding.
7 * @param encrypted {Uint8Array} the encrypted bytes
8 * @param key {Uint32Array} the bytes of the decryption key
9 * @param initVector {Uint32Array} the initialization vector (IV) to
10 * use for the first round of CBC.
11 * @return {Uint8Array} the decrypted bytes
12 *
13 * @see http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
14 * @see http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_.28CBC.29
15 * @see https://tools.ietf.org/html/rfc2315
16 */
17 /* eslint-enable max-len */
18 const decrypt = function(encrypted, key, initVector) {
19 // word-level access to the encrypted bytes
20 let encrypted32 = new Int32Array(encrypted.buffer,
21 encrypted.byteOffset,
22 encrypted.byteLength >> 2);
23
24 let decipher = new AES(Array.prototype.slice.call(key));
25
26 // byte and word-level access for the decrypted output
27 let decrypted = new Uint8Array(encrypted.byteLength);
28 let decrypted32 = new Int32Array(decrypted.buffer);
29
30 // temporary variables for working with the IV, encrypted, and
31 // decrypted data
32 let init0;
33 let init1;
34 let init2;
35 let init3;
36 let encrypted0;
37 let encrypted1;
38 let encrypted2;
39 let encrypted3;
40
41 // iteration variable
42 let wordIx;
43
44 // pull out the words of the IV to ensure we don't modify the
45 // passed-in reference and easier access
46 init0 = initVector[0];
47 init1 = initVector[1];
48 init2 = initVector[2];
49 init3 = initVector[3];
50
51 // decrypt four word sequences, applying cipher-block chaining (CBC)
52 // to each decrypted block
53 for (wordIx = 0; wordIx < encrypted32.length; wordIx += 4) {
54 // convert big-endian (network order) words into little-endian
55 // (javascript order)
56 encrypted0 = ntoh(encrypted32[wordIx]);
57 encrypted1 = ntoh(encrypted32[wordIx + 1]);
58 encrypted2 = ntoh(encrypted32[wordIx + 2]);
59 encrypted3 = ntoh(encrypted32[wordIx + 3]);
60
61 // decrypt the block
62 decipher.decrypt(encrypted0,
63 encrypted1,
64 encrypted2,
65 encrypted3,
66 decrypted32,
67 wordIx);
68
69 // XOR with the IV, and restore network byte-order to obtain the
70 // plaintext
71 decrypted32[wordIx] = ntoh(decrypted32[wordIx] ^ init0);
72 decrypted32[wordIx + 1] = ntoh(decrypted32[wordIx + 1] ^ init1);
73 decrypted32[wordIx + 2] = ntoh(decrypted32[wordIx + 2] ^ init2);
74 decrypted32[wordIx + 3] = ntoh(decrypted32[wordIx + 3] ^ init3);
75
76 // setup the IV for the next round
77 init0 = encrypted0;
78 init1 = encrypted1;
79 init2 = encrypted2;
80 init3 = encrypted3;
81 }
82
83 return decrypted;
84 };
85
86 export default decrypt;
1 import AES from './aes';
1 import AsyncStream from './async-stream'; 2 import AsyncStream from './async-stream';
2 import ntoh from './ntoh';
3 import {unpad} from 'pkcs7'; 3 import {unpad} from 'pkcs7';
4 import decrypt from './decrypt';
5 4
6 export default class Decrypter { 5 /**
6 * Convert network-order (big-endian) bytes into their little-endian
7 * representation.
8 */
9 const ntoh = function(word) {
10 return (word << 24) |
11 ((word & 0xff00) << 8) |
12 ((word & 0xff0000) >> 8) |
13 (word >>> 24);
14 };
15
16
17 /* eslint-disable max-len */
18 /**
19 * Decrypt bytes using AES-128 with CBC and PKCS#7 padding.
20 * @param encrypted {Uint8Array} the encrypted bytes
21 * @param key {Uint32Array} the bytes of the decryption key
22 * @param initVector {Uint32Array} the initialization vector (IV) to
23 * use for the first round of CBC.
24 * @return {Uint8Array} the decrypted bytes
25 *
26 * @see http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
27 * @see http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_.28CBC.29
28 * @see https://tools.ietf.org/html/rfc2315
29 */
30 /* eslint-enable max-len */
31 export const decrypt = function(encrypted, key, initVector) {
32 // word-level access to the encrypted bytes
33 let encrypted32 = new Int32Array(encrypted.buffer,
34 encrypted.byteOffset,
35 encrypted.byteLength >> 2);
36
37 let decipher = new AES(Array.prototype.slice.call(key));
38
39 // byte and word-level access for the decrypted output
40 let decrypted = new Uint8Array(encrypted.byteLength);
41 let decrypted32 = new Int32Array(decrypted.buffer);
42
43 // temporary variables for working with the IV, encrypted, and
44 // decrypted data
45 let init0;
46 let init1;
47 let init2;
48 let init3;
49 let encrypted0;
50 let encrypted1;
51 let encrypted2;
52 let encrypted3;
53
54 // iteration variable
55 let wordIx;
56
57 // pull out the words of the IV to ensure we don't modify the
58 // passed-in reference and easier access
59 init0 = initVector[0];
60 init1 = initVector[1];
61 init2 = initVector[2];
62 init3 = initVector[3];
63
64 // decrypt four word sequences, applying cipher-block chaining (CBC)
65 // to each decrypted block
66 for (wordIx = 0; wordIx < encrypted32.length; wordIx += 4) {
67 // convert big-endian (network order) words into little-endian
68 // (javascript order)
69 encrypted0 = ntoh(encrypted32[wordIx]);
70 encrypted1 = ntoh(encrypted32[wordIx + 1]);
71 encrypted2 = ntoh(encrypted32[wordIx + 2]);
72 encrypted3 = ntoh(encrypted32[wordIx + 3]);
73
74 // decrypt the block
75 decipher.decrypt(encrypted0,
76 encrypted1,
77 encrypted2,
78 encrypted3,
79 decrypted32,
80 wordIx);
81
82 // XOR with the IV, and restore network byte-order to obtain the
83 // plaintext
84 decrypted32[wordIx] = ntoh(decrypted32[wordIx] ^ init0);
85 decrypted32[wordIx + 1] = ntoh(decrypted32[wordIx + 1] ^ init1);
86 decrypted32[wordIx + 2] = ntoh(decrypted32[wordIx + 2] ^ init2);
87 decrypted32[wordIx + 3] = ntoh(decrypted32[wordIx + 3] ^ init3);
88
89 // setup the IV for the next round
90 init0 = encrypted0;
91 init1 = encrypted1;
92 init2 = encrypted2;
93 init3 = encrypted3;
94 }
95
96 return decrypted;
97 };
98
99
100 export class Decrypter {
7 constructor(encrypted, key, initVector, done) { 101 constructor(encrypted, key, initVector, done) {
8 let step = Decrypter.STEP; 102 let step = Decrypter.STEP;
9 let encrypted32 = new Int32Array(encrypted.buffer); 103 let encrypted32 = new Int32Array(encrypted.buffer);
...@@ -46,3 +140,7 @@ export default class Decrypter { ...@@ -46,3 +140,7 @@ export default class Decrypter {
46 // 4 * 8000; 140 // 4 * 8000;
47 Decrypter.STEP = 32000; 141 Decrypter.STEP = 32000;
48 142
143 export default {
144 Decrypter,
145 decrypt
146 };
......
1 import decrypt from './decrypt'; 1 import {decrypt, Decrypter} from './decrypter';
2 import AsyncStream from './async-stream'; 2 import AsyncStream from './async-stream';
3 import Decrypter from './decrypter';
4 3
5 export default { 4 export default {
6 decrypt, 5 decrypt,
......
1 /**
2 * Convert network-order (big-endian) bytes into their little-endian
3 * representation.
4 */
5 const ntoh = function(word) {
6 return (word << 24) |
7 ((word & 0xff00) << 8) |
8 ((word & 0xff0000) >> 8) |
9 (word >>> 24);
10 };
11
12 export default ntoh;