javascript-blowfish

Blowfish encryption library Javascript, jquery,coffeescript (blowfish.js)

Script này sẽ không được không được cài đặt trực tiếp. Nó là một thư viện cho các script khác để bao gồm các chỉ thị meta // @require https://update.greasyfork.org/scripts/447701/1069157/javascript-blowfish.js

  1. /**
  2. * The MIT License (MIT)
  3. *
  4. * Copyright (c) 2017 Alexandr Gorlov
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included
  14. * in all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. * SOFTWARE.
  23. */
  24.  
  25. /**
  26. * @class Blowfish
  27. * @description
  28. * Шифратор/дешифратор. Алгоритм Blowfish
  29. *
  30. * Browser version. For node use Blowfish.node.js
  31. *
  32. * в режиме ecb: исходная строка разбивается на 8-байтные блоки, каждый блок
  33. * шифруется. Если размер блока менее 8 байт, то дополняем его до 8 байт нулями.
  34. * в режиме cbc: первый блок открытого текста, из 8 байт, перед шифрованием побитово
  35. * складывается по модулю 2 (операция XOR) с вектором инициализации;
  36. * последующие блоки открытого текста побитового складываются (XOR) с предыдущим результатом
  37. * шифрования после этого зашифровываются.
  38. *
  39. * Подробнее о режимах шифрования:
  40. * http://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D0%B6%D0%B8%D0%BC_%D1%88%D0%B8%D1%84%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F
  41. *
  42. * @example
  43. * // Пример 1: режим ECB, по умолчанию
  44. * var bf = new Blowfish("secret key");
  45. * var encrypted = bf.encrypt("конфиденциальное сообщение");
  46. * var decrypted = bf.decrypt(encrypted);
  47. *
  48. * // Пример 2: режим CBC (лучше подходит для шифрования длинных сообщений, более 1kb):
  49. * var bf = new Blowfish("key", "cbc");
  50. * var encrypted = bf.encrypt("secret message", "cbcvecto");
  51. * var decrypted = bf.decrypt(encrypted, "cbcvecto");
  52. *
  53. * //В режиме CBC вектор иницаилазиации iv это дополнительный пароль.
  54. *
  55. * // Пример 3:
  56. * // После шифрования получается бинарная строка. Чтобы передать
  57. * // зашифрованное сообщение в эл.письме нужно закодировать бинарную
  58. * // строку в base64
  59. * var bf = new Blowfish("key");
  60. *
  61. * // Для удобства включил, в этот класс методы base64Encode и base64Decode
  62. *
  63. * // Шифрование
  64. * var encrypted = bf.base64Encode(bf.encrypt("secret message"));
  65. *
  66. * // Расшифрование
  67. * var encrypted = bf.base64Decode(encrypted);
  68. * var decrypted = bf.decrypt(encrypted);
  69. *
  70. * @param {string} key пароль (может быть длинной до 56 байт)
  71. * @param {string} [mode] режим шифрования
  72. * @author Alexandr Gorlov <a.gorlov@gmail.com>
  73. */
  74. var Blowfish = function(key, mode) {
  75.  
  76. // инициализация пароля
  77. this.key = key;
  78.  
  79. // инициализация режима шифрования
  80. if (mode === "ecb" || mode === "cbc") {
  81. this.mode = mode;
  82. }
  83.  
  84. // инициализация массивов с кодами символов (правда ведь?)
  85. this.sBox0 = Blowfish.sBox0.slice();
  86. this.sBox1 = Blowfish.sBox1.slice();
  87. this.sBox2 = Blowfish.sBox2.slice();
  88. this.sBox3 = Blowfish.sBox3.slice();
  89. this.pArray = Blowfish.pArray.slice();
  90.  
  91. // инициализация шифра
  92. this.generateSubkeys(key);
  93. };
  94.  
  95. Blowfish.prototype = {
  96.  
  97. /**
  98. * @type {Array}
  99. */
  100. sBox0: null,
  101.  
  102. /**
  103. * @type {Array}
  104. */
  105. sBox1: null,
  106.  
  107. /**
  108. * @type {Array}
  109. */
  110. sBox2: null,
  111.  
  112. /**
  113. * @type {Array}
  114. */
  115. sBox3: null,
  116.  
  117. /**
  118. * @type {Array}
  119. */
  120. pArray: null,
  121.  
  122. /**
  123. * Пароль
  124. * @type {string}
  125. */
  126. key: null,
  127.  
  128. /**
  129. * Режим шифрования: ecb|cbc; по умолчанию: ecb
  130. * @type {string}
  131. */
  132. mode: "ecb",
  133.  
  134. /**
  135. * Вектор инициализации для режима cbc
  136. * @type {string}
  137. */
  138. iv: "abc12345",
  139.  
  140. /**
  141. * Набор символов для base64
  142. * @type {string}
  143. */
  144. keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
  145.  
  146. /**
  147. * Шифрует строку
  148. * @param {string} string шифруемая строка
  149. * @param {string} iv произвольная 8байтная строка - вектор инициализации;
  150. * используется только в режиме CBC
  151. * @throws {Error} кидает исключение при неизвестном режиме шифрования
  152. * @return {string} зашифрованная строка
  153. */
  154. encrypt: function(string, iv) {
  155. if (this.mode === "ecb") {
  156. return this.encryptECB(string);
  157. }
  158.  
  159. if (this.mode === "cbc") {
  160. return this.encryptCBC(string, iv);
  161. }
  162.  
  163. throw new Error("Неизвестный режим шифрования.");
  164. },
  165.  
  166. /**
  167. * Расшифровывает строку
  168. * @param {string} string зашифрованная строка
  169. * @param {string} iv произвольная 8байтная строка - вектор инициализации
  170. * (должен быть тотже, что и при шифровании) используется
  171. * только в режиме CBC
  172. * @throws {Error} кидает исключение при неизвестном режиме шифрования
  173. * @return {string} расшифрованная строка
  174. */
  175. decrypt: function(string, iv) {
  176. if (this.mode === "ecb") {
  177. return this.decryptECB(string);
  178. }
  179.  
  180. if (this.mode === "cbc") {
  181. return this.decryptCBC(string, iv);
  182. }
  183.  
  184. throw new Error("Неизвестный режим шифрования.");
  185. },
  186.  
  187. /**
  188. * Шифрует в режиме ECB
  189. * (приватный метод)
  190. * @param {string} string шифруемая строка
  191. * @return {string} зашифрованная строка
  192. */
  193. encryptECB: function(string) {
  194. string = this.utf8Decode(string);
  195. var blocks = Math.ceil(string.length/8);
  196.  
  197. //1. разбить строку на 8-байтные блок-и
  198. //2. разбить 8байтные блоки на 32-битные пары xL, xR
  199. //3. зашифровать все блоки
  200. //4. преобразовать результат в строку
  201.  
  202. var encryptedString = "";
  203. for (var i = 0; i < blocks; i++) {
  204. var block = string.substr(i * 8, 8);
  205. if (block.length < 8) {
  206. var count = 8 - block.length;
  207. while (0 < count--) {
  208. block += "\0";
  209. }
  210. }
  211.  
  212. var xL, xR;
  213. //[xL, xR] = this.split64by32(block); не работает в IE, Chrome
  214. var xLxR = this.split64by32(block);
  215. xL = xLxR[0];
  216. xR = xLxR[1];
  217.  
  218. //[xL, xR] = this.encipher(xL, xR); не работает в IE, Chrome
  219. xLxR = this.encipher(xL, xR);
  220. xL = xLxR[0];
  221. xR = xLxR[1];
  222. encryptedString += this.num2block32(xL) + this.num2block32(xR);
  223. }
  224.  
  225. return encryptedString;
  226. },
  227.  
  228. /**
  229. * Шифрует в режиме CBC
  230. * (приватный метод)
  231. * @param {string} string шифруемая строка
  232. * @param {string} iv 8-байтная строка - вектор инициализации
  233. * @return {string} зашифрованная строка
  234. */
  235. encryptCBC: function(string, iv) {
  236. string = this.utf8Decode(string);
  237. var blocks = Math.ceil(string.length/8);
  238.  
  239. //1. разбить строку на 8-байтные блок-и
  240. //2. разбить 8байтные блоки на 32-битные пары xL, xR
  241. //3. зашифровать все блоки
  242. //4. преобразовать результат в строку
  243.  
  244. var ivL, ivR, ivLivR;
  245. //[ivL, ivR] = this.split64by32(iv);
  246. ivLivR = this.split64by32(iv);
  247. ivL = ivLivR[0];
  248. ivR = ivLivR[1];
  249.  
  250. var encryptedString = "";
  251. for (var i = 0; i < blocks; i++) {
  252. var block = string.substr(i * 8, 8);
  253. if (block.length < 8) {
  254. var count = 8 - block.length;
  255. while (0 < count--) {
  256. block += "\0";
  257. }
  258. }
  259.  
  260. var xL, xR, xLxR;
  261. xLxR = this.split64by32(block);
  262. xL = xLxR[0];
  263. xR = xLxR[1];
  264.  
  265. xL = this.xor(xL, ivL);
  266. xR = this.xor(xR, ivR);
  267.  
  268. xLxR = this.encipher(xL, xR);
  269. xL = xLxR[0];
  270. xR = xLxR[1];
  271.  
  272. ivL = xL;
  273. ivR = xR;
  274.  
  275. encryptedString += this.num2block32(xL) + this.num2block32(xR);
  276. }
  277.  
  278. return encryptedString;
  279. },
  280.  
  281. /**
  282. * Расшифровать в режиме ECB
  283. * (приватный метод)
  284. * @param {string} string шифруемая строка
  285. * @throws {Error} кидает исключение если зашифрованная строка повреждена
  286. * @return {string} зашифрованная строка
  287. */
  288. decryptECB: function(string) {
  289. var blocks = Math.ceil(string.length/8);
  290.  
  291. var decryptedString = "";
  292. for (var i = 0; i < blocks; i++) {
  293. var block = string.substr(i * 8, 8);
  294. if (block.length < 8) {
  295. throw new Error("Зашифрованная строка повреждена: длинна зашифрованной строки должна быть кратна 8 баыйтам.");
  296. }
  297. var xL, xR, xLxR;
  298.  
  299. xLxR = this.split64by32(block);
  300. xL = xLxR[0];
  301. xR = xLxR[1];
  302.  
  303. xLxR = this.decipher(xL, xR);
  304. xL = xLxR[0];
  305. xR = xLxR[1];
  306.  
  307. decryptedString += this.num2block32(xL) + this.num2block32(xR);
  308. }
  309.  
  310. decryptedString = this.utf8Encode(decryptedString);
  311. return decryptedString;
  312. },
  313.  
  314. /**
  315. * Шифрует в режиме CBC
  316. * (приватный метод)
  317. * @param {string} string зашифрованная строка
  318. * @param {string} iv 8-байтная строка - вектор инициализации
  319. * @throws {Error} кидает исключение если зашифрованная строка повреждена
  320. * @return {string} расшифрованая строка
  321. */
  322. decryptCBC: function(string, iv) {
  323.  
  324. var blocks = Math.ceil(string.length/8);
  325.  
  326. var ivL, ivR, ivLtmp, ivRtmp, ivLivR;
  327.  
  328. ivLivR = this.split64by32(iv);
  329. ivL = ivLivR[0];
  330. ivR = ivLivR[1];
  331.  
  332. var decryptedString = "";
  333. for (var i = 0; i < blocks; i++) {
  334. var block = string.substr(i * 8, 8);
  335. if (block.length < 8) {
  336. throw new Error("Зашифрованная строка повреждена: длинна зашифрованной строки должна быть кратна 8 байтам.");
  337. }
  338. var xL, xR, xLxR;
  339. xLxR = this.split64by32(block);
  340. xL = xLxR[0];
  341. xR = xLxR[1];
  342.  
  343. ivLtmp = xL;
  344. ivRtmp = xR;
  345.  
  346. xLxR = this.decipher(xL, xR);
  347. xL = xLxR[0];
  348. xR = xLxR[1];
  349.  
  350. xL = this.xor(xL, ivL);
  351. xR = this.xor(xR, ivR);
  352.  
  353. ivL = ivLtmp;
  354. ivR = ivRtmp;
  355. decryptedString += this.num2block32(xL) + this.num2block32(xR);
  356. }
  357.  
  358. decryptedString = this.utf8Encode(decryptedString);
  359. return decryptedString;
  360. },
  361.  
  362. /**
  363. * Функция F
  364. * Function F looks like this:
  365. * Divide xL into four eight-bit quarters: a, b, c, and d.
  366. * Then, F(xL) = ((S1,a + S2,b mod 232) XOR S3,c) + S4,d mod 232.
  367. * F(0xFFFFFF)
  368. * ((S1[255] + S2[255]) XOR S3[255]) + S4[255]
  369. * ((0x6e85076a + 0xdb83adf7) ^ 0x406000e0) + 0x3ac372e6
  370. * @param {int32} xL 32битное значение
  371. */
  372. F: function(xL) {
  373. var a = xL >>> 24;
  374. var b = xL << 8 >>> 24;
  375. var c = xL << 16 >>> 24;
  376. var d = xL << 24 >>> 24;
  377.  
  378. var res = this.addMod32(this.sBox0[a], this.sBox1[b]);
  379. res = this.xor(res, this.sBox2[c]);
  380. res = this.addMod32(res, this.sBox3[d]);
  381. return res;
  382. },
  383.  
  384. /**
  385. * Шифрует строку из 8 байт (один блок)
  386. * Encryption and Decryption:
  387. * Blowfish has 16 rounds. The input is a 64-bit data element, x.
  388. * Divide x into two 32-bit halves: xL, xR. Then, for i = 1 to 16:
  389. * xL = xL XOR Pi
  390. * xR = F(xL) XOR xR
  391. * Swap xL and xR
  392. * After the sixteenth round, swap xL and xR again to undo the last swap.
  393. * Then, xR = xR XOR P17 and xL = xL XOR P18. Finally, recombine xL and xR
  394. * to get the ciphertext.
  395. * Function F looks like this:
  396. * Divide xL into four eight-bit quarters: a, b, c, and d.
  397. * Then, F(xL) = ((S1,a + S2,b mod 232) XOR S3,c) + S4,d mod 232.
  398. * Decryption is exactly the same as encryption, except that P1, P2,..., P18
  399. * are used in the reverse order.
  400. * @param {int32} xL первые 4 символа в виде числа 32битного беззнакового
  401. * @param {int32} xR оставшиеся 4 символа в виде числа 32битного беззнакового
  402. * @return {Array} зашифрованный 8-байтный блок в виде пары 32битных чисел [xL, xR]
  403. */
  404. encipher: function(xL, xR) {
  405. var tmp;
  406. for (var i = 0; i < 16; i++) {
  407. xL = this.xor(xL, this.pArray[i]);
  408. xR = this.xor(this.F(xL), xR);
  409. tmp = xL;
  410. xL = xR;
  411. xR = tmp;
  412. }
  413.  
  414. tmp = xL;
  415. xL = xR;
  416. xR = tmp;
  417.  
  418. xR = this.xor(xR, this.pArray[16]);
  419. xL = this.xor(xL, this.pArray[17]);
  420.  
  421. return [xL, xR];
  422. },
  423.  
  424. /**
  425. * ??
  426. * @param {int32} xL
  427. * @param {int32} xR
  428. * @return {Array}
  429. */
  430. decipher: function(xL, xR) {
  431. var tmp;
  432.  
  433. xL = this.xor(xL, this.pArray[17]);
  434. xR = this.xor(xR, this.pArray[16]);
  435.  
  436. tmp = xL;
  437. xL = xR;
  438. xR = tmp;
  439.  
  440. for (var i = 15; i >= 0; i--) {
  441. tmp = xL;
  442. xL = xR;
  443. xR = tmp;
  444. xR = this.xor(this.F(xL), xR);
  445. xL = this.xor(xL, this.pArray[i]);
  446. }
  447.  
  448. return [xL, xR];
  449. },
  450.  
  451. /**
  452. * Генерация ключей (subkeys)
  453. * Generating the Subkeys:
  454. * The subkeys are calculated using the Blowfish algorithm:
  455. * 1. Initialize first the P-array and then the four S-boxes, in order,
  456. * with a fixed string. This string consists of the hexadecimal digits
  457. * of pi (less the initial 3): P1 = 0x243f6a88, P2 = 0x85a308d3,
  458. * P3 = 0x13198a2e, P4 = 0x03707344, etc.
  459. * 2. XOR P1 with the first 32 bits of the key, XOR P2 with the second 32-bits
  460. * of the key, and so on for all bits of the key (possibly up to P14).
  461. * Repeatedly cycle through the key bits until the entire P-array has
  462. * been XORed with key bits. (For every short key, there is at least one
  463. * equivalent longer key; for example, if A is a 64-bit key, then AA,
  464. * AAA, etc., are equivalent keys.)
  465. * 3. Encrypt the all-zero string with the Blowfish algorithm, using the
  466. * subkeys described in steps (1) and (2).
  467. * 4. Replace P1 and P2 with the output of step (3).
  468. * 5. Encrypt the output of step (3) using the Blowfish algorithm with the
  469. * modified subkeys.
  470. * 6. Replace P3 and P4 with the output of step (5).
  471. * 7. Continue the process, replacing all entries of the P array, and then all
  472. * four S-boxes in order, with the output of the continuously changing
  473. * Blowfish algorithm.
  474. * In total, 521 iterations are required to generate all required subkeys.
  475. * Applications can store the subkeys rather than execute this derivation
  476. * process multiple times.
  477. *
  478. * Долго пытался понять правильную последовательность генерации ключей,
  479. * в итоге посмотрел как сделано в PHP реализации Crypt_Blowfish (PEAR)
  480. * и разобрался.
  481. * @param {string} key ключ
  482. */
  483. generateSubkeys: function(key) {
  484. var data = 0;
  485. var k = 0;
  486. var i, j;
  487.  
  488. for (i = 0; i < 18; i++) {
  489. for (j = 4; j > 0; j--) {
  490. data = this.fixNegative(data << 8 | key.charCodeAt(k));
  491. k = (k + 1) % key.length;
  492. }
  493. this.pArray[i] = this.xor(this.pArray[i], data);
  494. data = 0;
  495. }
  496.  
  497. //var block64 = num2block32(0) + num2block32(0);
  498. var block64 = [0, 0];
  499. for (i = 0; i < 18; i += 2) {
  500. block64 = this.encipher(block64[0], block64[1]);
  501. this.pArray[i] = block64[0];
  502. this.pArray[i + 1] = block64[1];
  503. }
  504.  
  505. for (i = 0; i < 256; i += 2) {
  506. block64 = this.encipher(block64[0], block64[1]);
  507. this.sBox0[i] = block64[0];
  508. this.sBox0[i + 1] = block64[1];
  509. }
  510.  
  511. for (i = 0; i < 256; i += 2) {
  512. block64 = this.encipher(block64[0], block64[1]);
  513. this.sBox1[i] = block64[0];
  514. this.sBox1[i + 1] = block64[1];
  515. }
  516.  
  517. for (i = 0; i < 256; i += 2) {
  518. block64 = this.encipher(block64[0], block64[1]);
  519. this.sBox2[i] = block64[0];
  520. this.sBox2[i + 1] = block64[1];
  521. }
  522.  
  523. for (i = 0; i < 256; i += 2) {
  524. block64 = this.encipher(block64[0], block64[1]);
  525. this.sBox3[i] = block64[0];
  526. this.sBox3[i + 1] = block64[1];
  527. }
  528.  
  529. },
  530.  
  531. /**
  532. * Преобразует 4х байтную строку, в 32битное целое число
  533. * @param {string} block32
  534. * @return {int}
  535. */
  536. block32toNum: function(block32) {
  537. return this.fixNegative(
  538. block32.charCodeAt(0) << 24 |
  539. block32.charCodeAt(1) << 16 |
  540. block32.charCodeAt(2) << 8 |
  541. block32.charCodeAt(3)
  542. );
  543. },
  544.  
  545. /**
  546. * Преобразует 32битное число в строку (4 байта)
  547. * @param {int} num 32 битное число
  548. * @return {string} 4х-байтная строка
  549. */
  550. num2block32: function(num) {
  551. return String.fromCharCode(num >>> 24) +
  552. String.fromCharCode(num << 8 >>> 24) +
  553. String.fromCharCode(num << 16 >>> 24) +
  554. String.fromCharCode(num << 24 >>> 24);
  555. },
  556.  
  557. /**
  558. * Операция XOR
  559. * @param {int} a
  560. * @param {int} b
  561. * @return {int}
  562. */
  563. xor: function(a, b) {
  564. return this.fixNegative(a ^ b);
  565. },
  566.  
  567. /**
  568. * Сложение по модулю 2^32
  569. * Складываем 2 числа и отрбрасываем все разряды больше 32
  570. * @param {int} a
  571. * @param {int} b
  572. * @return {int}
  573. */
  574. addMod32: function(a, b) {
  575. return this.fixNegative((a + b) | 0); // | 0 приводит к 32битному значению
  576. },
  577.  
  578. /**
  579. * Преобразование signed int в unsigned int
  580. * после побитовых операций javascript возвращает знаковое число
  581. * However, for octet-data processing (eg, network stream, etc), usually
  582. * want the "unsigned int" representation. This can be accomplished by
  583. * adding a ">>> 0" (zero-fill right-shift) operator which internally tells
  584. * Javascript to treat this as unsigned.
  585. * @param {int} number целое число со знаком
  586. * @return {int} целое число без знака
  587. */
  588. fixNegative: function(number) {
  589. return number >>> 0;
  590. },
  591.  
  592. /**
  593. * Разделим 64 битный блок на два 32-битных
  594. * @param {string} block64 блок, состоящий из 64 бит (8 байт)
  595. * @return {Array} [xL, xR]
  596. */
  597. split64by32: function (block64) {
  598. var xL = block64.substring(0, 4);
  599. var xR = block64.substring(4, 8);
  600.  
  601. return [this.block32toNum(xL) , this.block32toNum(xR)];
  602. },
  603.  
  604. /**
  605. * Преобразует строку в последовательность байтов utf8
  606. * на один символ может приходится больше одного байта
  607. * Взял этот метод из библиотеки base64:
  608. * http://www.webtoolkit.info/javascript-base64.html
  609. */
  610. utf8Decode: function(string) {
  611. var utftext = "";
  612. for (var n = 0; n < string.length; n++) {
  613. var c = string.charCodeAt(n);
  614. if (c < 128) {
  615. utftext += String.fromCharCode(c);
  616. } else if (c > 127 && c < 2048) {
  617. utftext += String.fromCharCode(c >> 6 | 192);
  618. utftext += String.fromCharCode(c & 63 | 128);
  619. } else {
  620. utftext += String.fromCharCode(c >> 12 | 224);
  621. utftext += String.fromCharCode(c >> 6 & 63 | 128);
  622. utftext += String.fromCharCode(c & 63 | 128);
  623. }
  624. }
  625. return utftext;
  626. },
  627.  
  628. /**
  629. * Преобразует байтовую-строку utf8 в строку javascript
  630. */
  631. utf8Encode: function (utftext) {
  632. var string = "";
  633. var i = 0;
  634. var c = 0;
  635. var c1 = 0;
  636. var c2 = 0;
  637.  
  638. while ( i < utftext.length ) {
  639.  
  640. c = utftext.charCodeAt(i);
  641.  
  642. if (c < 128) {
  643. string += String.fromCharCode(c);
  644. i++;
  645. } else if((c > 191) && (c < 224)) {
  646. c1 = utftext.charCodeAt(i+1);
  647. string += String.fromCharCode(((c & 31) << 6) | (c1 & 63));
  648. i += 2;
  649. } else {
  650. c1 = utftext.charCodeAt(i+1);
  651. c2 = utftext.charCodeAt(i+2);
  652. string += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63));
  653. i += 3;
  654. }
  655.  
  656. }
  657.  
  658. return string;
  659. },
  660.  
  661. /**
  662. * Кодирует строку в base64
  663. * @param {string} input
  664. * @return {string}
  665. */
  666. base64Encode : function (input) {
  667. var output = "";
  668. var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
  669. var i = 0;
  670.  
  671. //input = this.utf8Encode(input);
  672.  
  673. while (i < input.length) {
  674. chr1 = input.charCodeAt(i++);
  675. chr2 = input.charCodeAt(i++);
  676. chr3 = input.charCodeAt(i++);
  677.  
  678. enc1 = chr1 >> 2;
  679. enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
  680. enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
  681. enc4 = chr3 & 63;
  682.  
  683. if (isNaN(chr2)) {
  684. enc3 = enc4 = 64;
  685. } else if (isNaN(chr3)) {
  686. enc4 = 64;
  687. }
  688.  
  689. output = output +
  690. this.keyStr.charAt(enc1) + this.keyStr.charAt(enc2) +
  691. this.keyStr.charAt(enc3) + this.keyStr.charAt(enc4);
  692. }
  693.  
  694. return output;
  695. },
  696.  
  697. /**
  698. * Раскодирует строку из base64
  699. * @param {string} input
  700. * @return {string}
  701. */
  702. base64Decode : function (input) {
  703. var output = "";
  704. var chr1, chr2, chr3;
  705. var enc1, enc2, enc3, enc4;
  706. var i = 0;
  707.  
  708. input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
  709.  
  710. while (i < input.length) {
  711.  
  712. enc1 = this.keyStr.indexOf(input.charAt(i++));
  713. enc2 = this.keyStr.indexOf(input.charAt(i++));
  714. enc3 = this.keyStr.indexOf(input.charAt(i++));
  715. enc4 = this.keyStr.indexOf(input.charAt(i++));
  716.  
  717. chr1 = (enc1 << 2) | (enc2 >> 4);
  718. chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
  719. chr3 = ((enc3 & 3) << 6) | enc4;
  720.  
  721. output = output + String.fromCharCode(chr1);
  722.  
  723. if (enc3 != 64) {
  724. output = output + String.fromCharCode(chr2);
  725. }
  726. if (enc4 != 64) {
  727. output = output + String.fromCharCode(chr3);
  728. }
  729.  
  730. }
  731.  
  732. //output = this.utf8Decode(output);
  733.  
  734. return output;
  735. },
  736.  
  737. /**
  738. * Удаляет символы \0 в конце строки
  739. * @param {string} input
  740. * @return {string}
  741. */
  742. trimZeros: function(input) {
  743. return input.replace(/\0+$/g, "");
  744. }
  745. }
  746.  
  747. /**
  748. * @static
  749. * @type {Array}
  750. */
  751. Blowfish.pArray = [
  752. 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
  753. 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
  754. 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b
  755. ];
  756.  
  757. /**
  758. * @static
  759. * @type {Array}
  760. */
  761. Blowfish.sBox0 = [
  762. 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
  763. 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
  764. 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
  765. 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
  766. 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
  767. 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
  768. 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
  769. 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
  770. 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
  771. 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
  772. 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
  773. 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
  774. 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
  775. 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
  776. 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
  777. 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
  778. 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
  779. 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
  780. 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
  781. 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
  782. 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
  783. 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
  784. 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
  785. 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
  786. 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
  787. 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
  788. 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
  789. 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
  790. 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
  791. 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
  792. 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
  793. 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
  794. 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
  795. 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
  796. 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
  797. 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
  798. 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
  799. 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
  800. 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
  801. 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
  802. 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
  803. 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
  804. 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
  805. ];
  806.  
  807. /**
  808. * @static
  809. * @type {Array}
  810. */
  811. Blowfish.sBox1 = [
  812. 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
  813. 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
  814. 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
  815. 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
  816. 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
  817. 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
  818. 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
  819. 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
  820. 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
  821. 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
  822. 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
  823. 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
  824. 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
  825. 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
  826. 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
  827. 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
  828. 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
  829. 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
  830. 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
  831. 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
  832. 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
  833. 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
  834. 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
  835. 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
  836. 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
  837. 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
  838. 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
  839. 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
  840. 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
  841. 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
  842. 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
  843. 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
  844. 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
  845. 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
  846. 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
  847. 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
  848. 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
  849. 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
  850. 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
  851. 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
  852. 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
  853. 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
  854. 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
  855. ];
  856.  
  857. /**
  858. * @static
  859. * @type {Array}
  860. */
  861. Blowfish.sBox2 = [
  862. 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
  863. 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
  864. 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
  865. 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
  866. 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
  867. 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
  868. 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
  869. 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
  870. 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
  871. 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
  872. 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
  873. 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
  874. 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
  875. 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
  876. 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
  877. 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
  878. 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
  879. 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
  880. 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
  881. 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
  882. 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
  883. 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
  884. 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
  885. 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
  886. 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
  887. 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
  888. 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
  889. 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
  890. 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
  891. 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
  892. 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
  893. 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
  894. 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
  895. 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
  896. 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
  897. 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
  898. 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
  899. 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
  900. 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
  901. 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
  902. 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
  903. 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
  904. 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
  905. ];
  906.  
  907. /**
  908. * @static
  909. * @type {Array}
  910. */
  911. Blowfish.sBox3 = [
  912. 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
  913. 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
  914. 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
  915. 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
  916. 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
  917. 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
  918. 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
  919. 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
  920. 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
  921. 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
  922. 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
  923. 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
  924. 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
  925. 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
  926. 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
  927. 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
  928. 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
  929. 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
  930. 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
  931. 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
  932. 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
  933. 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
  934. 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
  935. 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
  936. 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
  937. 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
  938. 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
  939. 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
  940. 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
  941. 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
  942. 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
  943. 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
  944. 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
  945. 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
  946. 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
  947. 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
  948. 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
  949. 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
  950. 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
  951. 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
  952. 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
  953. 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
  954. 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
  955. ];