aes-decrypter.cjs.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. /*! @name aes-decrypter @version 4.0.1 @license Apache-2.0 */
  2. 'use strict';
  3. Object.defineProperty(exports, '__esModule', { value: true });
  4. var Stream = require('@videojs/vhs-utils/cjs/stream.js');
  5. var pkcs7 = require('pkcs7');
  6. function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
  7. var Stream__default = /*#__PURE__*/_interopDefaultLegacy(Stream);
  8. /**
  9. * @file aes.js
  10. *
  11. * This file contains an adaptation of the AES decryption algorithm
  12. * from the Standford Javascript Cryptography Library. That work is
  13. * covered by the following copyright and permissions notice:
  14. *
  15. * Copyright 2009-2010 Emily Stark, Mike Hamburg, Dan Boneh.
  16. * All rights reserved.
  17. *
  18. * Redistribution and use in source and binary forms, with or without
  19. * modification, are permitted provided that the following conditions are
  20. * met:
  21. *
  22. * 1. Redistributions of source code must retain the above copyright
  23. * notice, this list of conditions and the following disclaimer.
  24. *
  25. * 2. Redistributions in binary form must reproduce the above
  26. * copyright notice, this list of conditions and the following
  27. * disclaimer in the documentation and/or other materials provided
  28. * with the distribution.
  29. *
  30. * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
  31. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  32. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  33. * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR CONTRIBUTORS BE
  34. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  35. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  36. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  37. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  38. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  39. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  40. * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  41. *
  42. * The views and conclusions contained in the software and documentation
  43. * are those of the authors and should not be interpreted as representing
  44. * official policies, either expressed or implied, of the authors.
  45. */
  46. /**
  47. * Expand the S-box tables.
  48. *
  49. * @private
  50. */
  51. const precompute = function () {
  52. const tables = [[[], [], [], [], []], [[], [], [], [], []]];
  53. const encTable = tables[0];
  54. const decTable = tables[1];
  55. const sbox = encTable[4];
  56. const sboxInv = decTable[4];
  57. let i;
  58. let x;
  59. let xInv;
  60. const d = [];
  61. const th = [];
  62. let x2;
  63. let x4;
  64. let x8;
  65. let s;
  66. let tEnc;
  67. let tDec; // Compute double and third tables
  68. for (i = 0; i < 256; i++) {
  69. th[(d[i] = i << 1 ^ (i >> 7) * 283) ^ i] = i;
  70. }
  71. for (x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) {
  72. // Compute sbox
  73. s = xInv ^ xInv << 1 ^ xInv << 2 ^ xInv << 3 ^ xInv << 4;
  74. s = s >> 8 ^ s & 255 ^ 99;
  75. sbox[x] = s;
  76. sboxInv[s] = x; // Compute MixColumns
  77. x8 = d[x4 = d[x2 = d[x]]];
  78. tDec = x8 * 0x1010101 ^ x4 * 0x10001 ^ x2 * 0x101 ^ x * 0x1010100;
  79. tEnc = d[s] * 0x101 ^ s * 0x1010100;
  80. for (i = 0; i < 4; i++) {
  81. encTable[i][x] = tEnc = tEnc << 24 ^ tEnc >>> 8;
  82. decTable[i][s] = tDec = tDec << 24 ^ tDec >>> 8;
  83. }
  84. } // Compactify. Considerable speedup on Firefox.
  85. for (i = 0; i < 5; i++) {
  86. encTable[i] = encTable[i].slice(0);
  87. decTable[i] = decTable[i].slice(0);
  88. }
  89. return tables;
  90. };
  91. let aesTables = null;
  92. /**
  93. * Schedule out an AES key for both encryption and decryption. This
  94. * is a low-level class. Use a cipher mode to do bulk encryption.
  95. *
  96. * @class AES
  97. * @param key {Array} The key as an array of 4, 6 or 8 words.
  98. */
  99. class AES {
  100. constructor(key) {
  101. /**
  102. * The expanded S-box and inverse S-box tables. These will be computed
  103. * on the client so that we don't have to send them down the wire.
  104. *
  105. * There are two tables, _tables[0] is for encryption and
  106. * _tables[1] is for decryption.
  107. *
  108. * The first 4 sub-tables are the expanded S-box with MixColumns. The
  109. * last (_tables[01][4]) is the S-box itself.
  110. *
  111. * @private
  112. */
  113. // if we have yet to precompute the S-box tables
  114. // do so now
  115. if (!aesTables) {
  116. aesTables = precompute();
  117. } // then make a copy of that object for use
  118. this._tables = [[aesTables[0][0].slice(), aesTables[0][1].slice(), aesTables[0][2].slice(), aesTables[0][3].slice(), aesTables[0][4].slice()], [aesTables[1][0].slice(), aesTables[1][1].slice(), aesTables[1][2].slice(), aesTables[1][3].slice(), aesTables[1][4].slice()]];
  119. let i;
  120. let j;
  121. let tmp;
  122. const sbox = this._tables[0][4];
  123. const decTable = this._tables[1];
  124. const keyLen = key.length;
  125. let rcon = 1;
  126. if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) {
  127. throw new Error('Invalid aes key size');
  128. }
  129. const encKey = key.slice(0);
  130. const decKey = [];
  131. this._key = [encKey, decKey]; // schedule encryption keys
  132. for (i = keyLen; i < 4 * keyLen + 28; i++) {
  133. tmp = encKey[i - 1]; // apply sbox
  134. if (i % keyLen === 0 || keyLen === 8 && i % keyLen === 4) {
  135. tmp = sbox[tmp >>> 24] << 24 ^ sbox[tmp >> 16 & 255] << 16 ^ sbox[tmp >> 8 & 255] << 8 ^ sbox[tmp & 255]; // shift rows and add rcon
  136. if (i % keyLen === 0) {
  137. tmp = tmp << 8 ^ tmp >>> 24 ^ rcon << 24;
  138. rcon = rcon << 1 ^ (rcon >> 7) * 283;
  139. }
  140. }
  141. encKey[i] = encKey[i - keyLen] ^ tmp;
  142. } // schedule decryption keys
  143. for (j = 0; i; j++, i--) {
  144. tmp = encKey[j & 3 ? i : i - 4];
  145. if (i <= 4 || j < 4) {
  146. decKey[j] = tmp;
  147. } else {
  148. decKey[j] = decTable[0][sbox[tmp >>> 24]] ^ decTable[1][sbox[tmp >> 16 & 255]] ^ decTable[2][sbox[tmp >> 8 & 255]] ^ decTable[3][sbox[tmp & 255]];
  149. }
  150. }
  151. }
  152. /**
  153. * Decrypt 16 bytes, specified as four 32-bit words.
  154. *
  155. * @param {number} encrypted0 the first word to decrypt
  156. * @param {number} encrypted1 the second word to decrypt
  157. * @param {number} encrypted2 the third word to decrypt
  158. * @param {number} encrypted3 the fourth word to decrypt
  159. * @param {Int32Array} out the array to write the decrypted words
  160. * into
  161. * @param {number} offset the offset into the output array to start
  162. * writing results
  163. * @return {Array} The plaintext.
  164. */
  165. decrypt(encrypted0, encrypted1, encrypted2, encrypted3, out, offset) {
  166. const key = this._key[1]; // state variables a,b,c,d are loaded with pre-whitened data
  167. let a = encrypted0 ^ key[0];
  168. let b = encrypted3 ^ key[1];
  169. let c = encrypted2 ^ key[2];
  170. let d = encrypted1 ^ key[3];
  171. let a2;
  172. let b2;
  173. let c2; // key.length === 2 ?
  174. const nInnerRounds = key.length / 4 - 2;
  175. let i;
  176. let kIndex = 4;
  177. const table = this._tables[1]; // load up the tables
  178. const table0 = table[0];
  179. const table1 = table[1];
  180. const table2 = table[2];
  181. const table3 = table[3];
  182. const sbox = table[4]; // Inner rounds. Cribbed from OpenSSL.
  183. for (i = 0; i < nInnerRounds; i++) {
  184. a2 = table0[a >>> 24] ^ table1[b >> 16 & 255] ^ table2[c >> 8 & 255] ^ table3[d & 255] ^ key[kIndex];
  185. b2 = table0[b >>> 24] ^ table1[c >> 16 & 255] ^ table2[d >> 8 & 255] ^ table3[a & 255] ^ key[kIndex + 1];
  186. c2 = table0[c >>> 24] ^ table1[d >> 16 & 255] ^ table2[a >> 8 & 255] ^ table3[b & 255] ^ key[kIndex + 2];
  187. d = table0[d >>> 24] ^ table1[a >> 16 & 255] ^ table2[b >> 8 & 255] ^ table3[c & 255] ^ key[kIndex + 3];
  188. kIndex += 4;
  189. a = a2;
  190. b = b2;
  191. c = c2;
  192. } // Last round.
  193. for (i = 0; i < 4; i++) {
  194. out[(3 & -i) + offset] = sbox[a >>> 24] << 24 ^ sbox[b >> 16 & 255] << 16 ^ sbox[c >> 8 & 255] << 8 ^ sbox[d & 255] ^ key[kIndex++];
  195. a2 = a;
  196. a = b;
  197. b = c;
  198. c = d;
  199. d = a2;
  200. }
  201. }
  202. }
  203. /**
  204. * @file async-stream.js
  205. */
  206. /**
  207. * A wrapper around the Stream class to use setTimeout
  208. * and run stream "jobs" Asynchronously
  209. *
  210. * @class AsyncStream
  211. * @extends Stream
  212. */
  213. class AsyncStream extends Stream__default["default"] {
  214. constructor() {
  215. super(Stream__default["default"]);
  216. this.jobs = [];
  217. this.delay = 1;
  218. this.timeout_ = null;
  219. }
  220. /**
  221. * process an async job
  222. *
  223. * @private
  224. */
  225. processJob_() {
  226. this.jobs.shift()();
  227. if (this.jobs.length) {
  228. this.timeout_ = setTimeout(this.processJob_.bind(this), this.delay);
  229. } else {
  230. this.timeout_ = null;
  231. }
  232. }
  233. /**
  234. * push a job into the stream
  235. *
  236. * @param {Function} job the job to push into the stream
  237. */
  238. push(job) {
  239. this.jobs.push(job);
  240. if (!this.timeout_) {
  241. this.timeout_ = setTimeout(this.processJob_.bind(this), this.delay);
  242. }
  243. }
  244. }
  245. /**
  246. * @file decrypter.js
  247. *
  248. * An asynchronous implementation of AES-128 CBC decryption with
  249. * PKCS#7 padding.
  250. */
  251. /**
  252. * Convert network-order (big-endian) bytes into their little-endian
  253. * representation.
  254. */
  255. const ntoh = function (word) {
  256. return word << 24 | (word & 0xff00) << 8 | (word & 0xff0000) >> 8 | word >>> 24;
  257. };
  258. /**
  259. * Decrypt bytes using AES-128 with CBC and PKCS#7 padding.
  260. *
  261. * @param {Uint8Array} encrypted the encrypted bytes
  262. * @param {Uint32Array} key the bytes of the decryption key
  263. * @param {Uint32Array} initVector the initialization vector (IV) to
  264. * use for the first round of CBC.
  265. * @return {Uint8Array} the decrypted bytes
  266. *
  267. * @see http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
  268. * @see http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_.28CBC.29
  269. * @see https://tools.ietf.org/html/rfc2315
  270. */
  271. const decrypt = function (encrypted, key, initVector) {
  272. // word-level access to the encrypted bytes
  273. const encrypted32 = new Int32Array(encrypted.buffer, encrypted.byteOffset, encrypted.byteLength >> 2);
  274. const decipher = new AES(Array.prototype.slice.call(key)); // byte and word-level access for the decrypted output
  275. const decrypted = new Uint8Array(encrypted.byteLength);
  276. const decrypted32 = new Int32Array(decrypted.buffer); // temporary variables for working with the IV, encrypted, and
  277. // decrypted data
  278. let init0;
  279. let init1;
  280. let init2;
  281. let init3;
  282. let encrypted0;
  283. let encrypted1;
  284. let encrypted2;
  285. let encrypted3; // iteration variable
  286. let wordIx; // pull out the words of the IV to ensure we don't modify the
  287. // passed-in reference and easier access
  288. init0 = initVector[0];
  289. init1 = initVector[1];
  290. init2 = initVector[2];
  291. init3 = initVector[3]; // decrypt four word sequences, applying cipher-block chaining (CBC)
  292. // to each decrypted block
  293. for (wordIx = 0; wordIx < encrypted32.length; wordIx += 4) {
  294. // convert big-endian (network order) words into little-endian
  295. // (javascript order)
  296. encrypted0 = ntoh(encrypted32[wordIx]);
  297. encrypted1 = ntoh(encrypted32[wordIx + 1]);
  298. encrypted2 = ntoh(encrypted32[wordIx + 2]);
  299. encrypted3 = ntoh(encrypted32[wordIx + 3]); // decrypt the block
  300. decipher.decrypt(encrypted0, encrypted1, encrypted2, encrypted3, decrypted32, wordIx); // XOR with the IV, and restore network byte-order to obtain the
  301. // plaintext
  302. decrypted32[wordIx] = ntoh(decrypted32[wordIx] ^ init0);
  303. decrypted32[wordIx + 1] = ntoh(decrypted32[wordIx + 1] ^ init1);
  304. decrypted32[wordIx + 2] = ntoh(decrypted32[wordIx + 2] ^ init2);
  305. decrypted32[wordIx + 3] = ntoh(decrypted32[wordIx + 3] ^ init3); // setup the IV for the next round
  306. init0 = encrypted0;
  307. init1 = encrypted1;
  308. init2 = encrypted2;
  309. init3 = encrypted3;
  310. }
  311. return decrypted;
  312. };
  313. /**
  314. * The `Decrypter` class that manages decryption of AES
  315. * data through `AsyncStream` objects and the `decrypt`
  316. * function
  317. *
  318. * @param {Uint8Array} encrypted the encrypted bytes
  319. * @param {Uint32Array} key the bytes of the decryption key
  320. * @param {Uint32Array} initVector the initialization vector (IV) to
  321. * @param {Function} done the function to run when done
  322. * @class Decrypter
  323. */
  324. class Decrypter {
  325. constructor(encrypted, key, initVector, done) {
  326. const step = Decrypter.STEP;
  327. const encrypted32 = new Int32Array(encrypted.buffer);
  328. const decrypted = new Uint8Array(encrypted.byteLength);
  329. let i = 0;
  330. this.asyncStream_ = new AsyncStream(); // split up the encryption job and do the individual chunks asynchronously
  331. this.asyncStream_.push(this.decryptChunk_(encrypted32.subarray(i, i + step), key, initVector, decrypted));
  332. for (i = step; i < encrypted32.length; i += step) {
  333. initVector = new Uint32Array([ntoh(encrypted32[i - 4]), ntoh(encrypted32[i - 3]), ntoh(encrypted32[i - 2]), ntoh(encrypted32[i - 1])]);
  334. this.asyncStream_.push(this.decryptChunk_(encrypted32.subarray(i, i + step), key, initVector, decrypted));
  335. } // invoke the done() callback when everything is finished
  336. this.asyncStream_.push(function () {
  337. // remove pkcs#7 padding from the decrypted bytes
  338. done(null, pkcs7.unpad(decrypted));
  339. });
  340. }
  341. /**
  342. * a getter for step the maximum number of bytes to process at one time
  343. *
  344. * @return {number} the value of step 32000
  345. */
  346. static get STEP() {
  347. // 4 * 8000;
  348. return 32000;
  349. }
  350. /**
  351. * @private
  352. */
  353. decryptChunk_(encrypted, key, initVector, decrypted) {
  354. return function () {
  355. const bytes = decrypt(encrypted, key, initVector);
  356. decrypted.set(bytes, encrypted.byteOffset);
  357. };
  358. }
  359. }
  360. exports.AsyncStream = AsyncStream;
  361. exports.Decrypter = Decrypter;
  362. exports.decrypt = decrypt;