des.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. var Base64 = require("./base64")
  2. var des3iv = '12345678';
  3. /**
  4. * 3DES加密,ECB/PKCS5Padding
  5. */
  6. function encrypt(data, key) {
  7. var genKey = genkey(key, 0, 24);
  8. var str = des(genKey.key, data, 1, 0, des3iv, 0);
  9. return Base64.base64encode(str);
  10. }
  11. module.exports.encrypt = encrypt;
  12. /**
  13. * 3DES解密,ECB/PKCS5Padding
  14. */
  15. function decrypt(data, key) {
  16. var genKey = genkey(key, 0, 24);
  17. var str = Base64.base64decode(data);
  18. return des(genKey.key, str, 0, 0, des3iv, 0);
  19. }
  20. module.exports.decrypt = decrypt;
  21. /**
  22. * DES 加密算法
  23. *
  24. * 该函数接受一个 8 字节字符串作为普通 DES 算法的密钥(也就是 64 位,但是算法只使用 56 位),或者接受一个 24 字节字符串作为 3DES
  25. * 算法的密钥;第二个参数是要加密或解密的信息字符串;第三个布尔值参数用来说明信息是加密还是解密;接下来的可选参数 mode 如果是 0 表示 ECB
  26. * 模式,1 表示 CBC 模式,默认是 ECB 模式;最后一个可选项是一个 8 字节的输入向量字符串(在 ECB 模式下不使用)。返回的密文是字符串。
  27. *
  28. * 参数: <br>
  29. * key: 8字节字符串作为普通 DES 算法的密钥,或 24 字节字符串作为 3DES <br>
  30. * message: 加密或解密的信息字符串<br>
  31. * encrypt: 布尔值参数用来说明信息是加密还是解密<br>
  32. * mode: 1:CBC模式,0:ECB模式(默认)<br>
  33. * iv:<br>
  34. * padding: 可选项, 8字节的输入向量字符串(在 ECB 模式下不使用)
  35. */
  36. //des http://www.cnblogs.com/bullub/archive/2013/05/02/3054798.html
  37. //this takes the key, the message, and whether to encrypt or decrypt
  38. function des(key, message, encrypt, mode, iv, padding) {
  39. if (encrypt) {//如果是加密的话,首先转换编码
  40. message = unescape(encodeURIComponent(message));
  41. }
  42. //declaring this locally speeds things up a bit
  43. var spfunction1 = new Array(0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000, 0x400, 0x1010400, 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, 0x10404, 0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404, 0x1000400, 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004);
  44. var spfunction2 = new Array(-0x7fef7fe0, -0x7fff8000, 0x8000, 0x108020, 0x100000, 0x20, -0x7fefffe0, -0x7fff7fe0, -0x7fffffe0, -0x7fef7fe0, -0x7fef8000, -0x80000000, -0x7fff8000, 0x100000, 0x20, -0x7fefffe0, 0x108000, 0x100020, -0x7fff7fe0, 0, -0x80000000, 0x8000, 0x108020, -0x7ff00000, 0x100020, -0x7fffffe0, 0, 0x108000, 0x8020, -0x7fef8000, -0x7ff00000, 0x8020, 0, 0x108020, -0x7fefffe0, 0x100000, -0x7fff7fe0, -0x7ff00000, -0x7fef8000, 0x8000, -0x7ff00000, -0x7fff8000, 0x20, -0x7fef7fe0, 0x108020, 0x20, 0x8000, -0x80000000, 0x8020, -0x7fef8000, 0x100000, -0x7fffffe0, 0x100020, -0x7fff7fe0, -0x7fffffe0, 0x100020, 0x108000, 0, -0x7fff8000, 0x8020, -0x80000000, -0x7fefffe0, -0x7fef7fe0, 0x108000);
  45. var spfunction3 = new Array(0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008, 0x8000008, 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200, 0x200, 0x20200, 0x8020000, 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8, 0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, 0x8020008, 0x8000208, 0x20000, 0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, 0x8020000, 0x20208, 0x8, 0x8020008, 0x20200);
  46. var spfunction4 = new Array(0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001, 0, 0x802000, 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080, 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, 0, 0x802000, 0x2080, 0x800080, 0x800081, 0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, 0x2001, 0x802080, 0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080);
  47. var spfunction5 = new Array(0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000, 0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000, 0x40080000, 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, 0x40080000, 0x2080100, 0x40000100);
  48. var spfunction6 = new Array(0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000, 0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010, 0x20004010, 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010, 0x400000, 0x20004000, 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010);
  49. var spfunction7 = new Array(0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802, 0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, 0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800, 0x4000000, 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800, 0x200000, 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2, 0x4200802, 0, 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002);
  50. var spfunction8 = new Array(0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000, 0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040, 0x10001000, 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040, 0x10001000, 0x40, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000);
  51. //create the 16 or 48 subkeys we will need
  52. var keys = des_createKeys(key);
  53. var m = 0, i, j, temp, temp2, right1, right2, left, right, looping;
  54. var cbcleft, cbcleft2, cbcright, cbcright2
  55. var endloop, loopinc;
  56. var len = message.length;
  57. var chunk = 0;
  58. //set up the loops for single and triple des
  59. var iterations = keys.length == 32 ? 3 : 9; //single or triple des
  60. if (iterations == 3) {
  61. looping = encrypt ? new Array(0, 32, 2) : new Array(30, -2, -2);
  62. } else {
  63. looping = encrypt ? new Array(0, 32, 2, 62, 30, -2, 64, 96, 2) : new Array(94, 62, -2, 32, 64, 2, 30, -2, -2);
  64. }
  65. //pad the message depending on the padding parameter
  66. if (padding == 2) {
  67. message += " "; //pad the message with spaces
  68. } else if (padding == 1) { //PKCS5Padding
  69. if (encrypt) {
  70. temp = 8 - (len % 8);
  71. message += String.fromCharCode(temp, temp, temp, temp, temp, temp, temp, temp);
  72. if (temp === 8) len += 8;
  73. }
  74. } else if (!padding) { //NoPadding
  75. // message += "\0\0\0\0\0\0\0\0"; //pad the message out with null bytes
  76. if (encrypt) {
  77. var mesByte = stringToByte(message);
  78. var iLen = mesByte.length % 8;
  79. var padByte = [], desByte = [];
  80. if (iLen == 0) {
  81. padByte = new Array(8).fill(0);
  82. var desByte = new Array(mesByte.length + 8);
  83. for (var i = 0; i < mesByte.length; i++) {
  84. desByte[i] = mesByte[i];
  85. }
  86. for (var j = 0; j < 8; j++) {
  87. desByte[mesByte.length + j] = padByte[j];
  88. }
  89. message = byteToString(desByte);
  90. len = message.length;
  91. } else {
  92. var pLen = 8 - iLen;
  93. padByte = new Array(pLen).fill(0);
  94. var desByte = new Array(mesByte.length + pLen);
  95. for (var i = 0; i < mesByte.length; i++) {
  96. desByte[i] = mesByte[i];
  97. }
  98. for (var j = 0; j < pLen; j++) {
  99. desByte[mesByte.length + j] = padByte[j];
  100. }
  101. message = byteToString(desByte);
  102. len = message.length;
  103. }
  104. }
  105. }
  106. //store the result here
  107. var result = "";
  108. var tempresult = "";
  109. if (mode == 1) { //CBC mode
  110. cbcleft = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++);
  111. cbcright = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++);
  112. m = 0;
  113. }
  114. //loop through each 64 bit chunk of the message
  115. while (m < len) {
  116. left = (message.charCodeAt(m++) << 24) | (message.charCodeAt(m++) << 16) | (message.charCodeAt(m++) << 8) | message.charCodeAt(m++);
  117. right = (message.charCodeAt(m++) << 24) | (message.charCodeAt(m++) << 16) | (message.charCodeAt(m++) << 8) | message.charCodeAt(m++);
  118. //for Cipher Block Chaining mode, xor the message with the previous result
  119. if (mode == 1) {
  120. if (encrypt) {
  121. left ^= cbcleft; right ^= cbcright;
  122. } else {
  123. cbcleft2 = cbcleft; cbcright2 = cbcright; cbcleft = left; cbcright = right;
  124. }
  125. }
  126. //first each 64 but chunk of the message must be permuted according to IP
  127. temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
  128. temp = ((left >>> 16) ^ right) & 0x0000ffff; right ^= temp; left ^= (temp << 16);
  129. temp = ((right >>> 2) ^ left) & 0x33333333; left ^= temp; right ^= (temp << 2);
  130. temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
  131. temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
  132. left = ((left << 1) | (left >>> 31));
  133. right = ((right << 1) | (right >>> 31));
  134. //do this either 1 or 3 times for each chunk of the message
  135. for (j = 0; j < iterations; j += 3) {
  136. endloop = looping[j + 1];
  137. loopinc = looping[j + 2];
  138. //now go through and perform the encryption or decryption
  139. for (i = looping[j]; i != endloop; i += loopinc) { //for efficiency
  140. right1 = right ^ keys[i];
  141. right2 = ((right >>> 4) | (right << 28)) ^ keys[i + 1];
  142. //the result is attained by passing these bytes through the S selection functions
  143. temp = left;
  144. left = right;
  145. right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f]
  146. | spfunction6[(right1 >>> 8) & 0x3f] | spfunction8[right1 & 0x3f]
  147. | spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & 0x3f]
  148. | spfunction5[(right2 >>> 8) & 0x3f] | spfunction7[right2 & 0x3f]);
  149. }
  150. temp = left; left = right; right = temp; //unreverse left and right
  151. } //for either 1 or 3 iterations
  152. //move then each one bit to the right
  153. left = ((left >>> 1) | (left << 31));
  154. right = ((right >>> 1) | (right << 31));
  155. //now perform IP-1, which is IP in the opposite direction
  156. temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
  157. temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
  158. temp = ((right >>> 2) ^ left) & 0x33333333; left ^= temp; right ^= (temp << 2);
  159. temp = ((left >>> 16) ^ right) & 0x0000ffff; right ^= temp; left ^= (temp << 16);
  160. temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
  161. //for Cipher Block Chaining mode, xor the message with the previous result
  162. if (mode == 1) {
  163. if (encrypt) {
  164. cbcleft = left; cbcright = right;
  165. } else {
  166. left ^= cbcleft2; right ^= cbcright2;
  167. }
  168. }
  169. tempresult += String.fromCharCode((left >>> 24), ((left >>> 16) & 0xff), ((left >>> 8) & 0xff), (left & 0xff), (right >>> 24), ((right >>> 16) & 0xff), ((right >>> 8) & 0xff), (right & 0xff));
  170. chunk += 8;
  171. if (chunk == 512) {
  172. result += tempresult; tempresult = ""; chunk = 0;
  173. }
  174. } //for every 8 characters, or 64 bits in the message
  175. //return the result as an array
  176. result += tempresult;
  177. result = result.replace(/\0*$/g, "");
  178. if (!encrypt) { //如果是解密的话,解密结束后对PKCS7 padding进行解码,并转换成utf-8编码
  179. if (padding === 1) { //PKCS7 padding解码
  180. var len = result.length, paddingChars = 0;
  181. len && (paddingChars = result.charCodeAt(len - 1));
  182. (paddingChars <= 8) && (result = result.substring(0, len - paddingChars));
  183. }
  184. //转换成UTF-8编码
  185. result = decodeURIComponent(escape(result));
  186. }
  187. return result;
  188. } //end of des
  189. //des_createKeys
  190. //this takes as input a 64 bit key (even though only 56 bits are used)
  191. //as an array of 2 integers, and returns 16 48 bit keys
  192. function des_createKeys(key) {
  193. //declaring this locally speeds things up a bit
  194. var pc2bytes0 = new Array(0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004, 0x200, 0x204, 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204);
  195. var pc2bytes1 = new Array(0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001, 0x100, 0x101, 0x100100, 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101);
  196. var pc2bytes2 = new Array(0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808);
  197. var pc2bytes3 = new Array(0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000, 0x20000, 0x220000, 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000);
  198. var pc2bytes4 = new Array(0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010, 0x41010, 0x1000, 0x41000, 0x1010, 0x41010);
  199. var pc2bytes5 = new Array(0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020, 0x2000420, 0x2000000, 0x2000400, 0x2000020, 0x2000420);
  200. var pc2bytes6 = new Array(0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002);
  201. var pc2bytes7 = new Array(0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000, 0x30000, 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800);
  202. var pc2bytes8 = new Array(0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000, 0x2040000, 0x2000002, 0x2040002, 0x2000002, 0x2040002);
  203. var pc2bytes9 = new Array(0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408, 0x10000408, 0x400, 0x10000400, 0x408, 0x10000408);
  204. var pc2bytes10 = new Array(0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020, 0x102000, 0x102020, 0x102000, 0x102020);
  205. var pc2bytes11 = new Array(0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000, 0x5000000, 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200);
  206. var pc2bytes12 = new Array(0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010, 0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010);
  207. var pc2bytes13 = new Array(0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105);
  208. //how many iterations (1 for des, 3 for triple des)
  209. var iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys
  210. //stores the return keys
  211. var keys = new Array(32 * iterations);
  212. //now define the left shifts which need to be done
  213. var shifts = new Array(0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0);
  214. //other variables
  215. var lefttemp, righttemp, m = 0, n = 0, temp;
  216. for (var j = 0; j < iterations; j++) { //either 1 or 3 iterations
  217. var left = (key.charCodeAt(m++) << 24) | (key.charCodeAt(m++) << 16) | (key.charCodeAt(m++) << 8) | key.charCodeAt(m++);
  218. var right = (key.charCodeAt(m++) << 24) | (key.charCodeAt(m++) << 16) | (key.charCodeAt(m++) << 8) | key.charCodeAt(m++);
  219. temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
  220. temp = ((right >>> -16) ^ left) & 0x0000ffff; left ^= temp; right ^= (temp << -16);
  221. temp = ((left >>> 2) ^ right) & 0x33333333; right ^= temp; left ^= (temp << 2);
  222. temp = ((right >>> -16) ^ left) & 0x0000ffff; left ^= temp; right ^= (temp << -16);
  223. temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
  224. temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
  225. temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
  226. //the right side needs to be shifted and to get the last four bits of the left side
  227. temp = (left << 8) | ((right >>> 20) & 0x000000f0);
  228. //left needs to be put upside down
  229. left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0);
  230. right = temp;
  231. //now go through and perform these shifts on the left and right keys
  232. for (var i = 0; i < shifts.length; i++) {
  233. //shift the keys either one or two bits to the left
  234. if (shifts[i]) {
  235. left = (left << 2) | (left >>> 26); right = (right << 2) | (right >>> 26);
  236. } else {
  237. left = (left << 1) | (left >>> 27); right = (right << 1) | (right >>> 27);
  238. }
  239. left &= -0xf; right &= -0xf;
  240. //now apply PC-2, in such a way that E is easier when encrypting or decrypting
  241. //this conversion will look like PC-2 except only the last 6 bits of each byte are used
  242. //rather than 48 consecutive bits and the order of lines will be according to
  243. //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7
  244. lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf]
  245. | pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[(left >>> 16) & 0xf]
  246. | pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf]
  247. | pc2bytes6[(left >>> 4) & 0xf];
  248. righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf]
  249. | pc2bytes9[(right >>> 20) & 0xf] | pc2bytes10[(right >>> 16) & 0xf]
  250. | pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf]
  251. | pc2bytes13[(right >>> 4) & 0xf];
  252. temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff;
  253. keys[n++] = lefttemp ^ temp; keys[n++] = righttemp ^ (temp << 16);
  254. }
  255. } //for each iterations
  256. //return the keys we've created
  257. return keys;
  258. } //end of des_createKeys
  259. function genkey(key, start, end) {
  260. //8 byte / 64 bit Key (DES) or 192 bit Key
  261. return { key: pad(key.slice(start, end)), vector: 1 };
  262. }
  263. function pad(key) {
  264. for (var i = key.length; i < 24; i++) {
  265. key += "0";
  266. }
  267. return key;
  268. }
  269. function stringToHex(str) {
  270. var res = "0x";
  271. var hexes = new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f");
  272. for (var i = 0; i < str.length; i++) {
  273. res += hexes[str.charCodeAt(i) >> 4] + hexes[str.charCodeAt(i) & 0xf];
  274. }
  275. return res;
  276. }
  277. function hexToString(hexStr) {
  278. var res = "";
  279. for (var i = (hexStr.substr(0, 2) == "0x") ? 2 : 0; i < hexStr.length; i += 2) {
  280. res += String.fromCharCode(parseInt(hexStr.substr(i, 2), 16));
  281. }
  282. return res;
  283. }
  284. function byteToString(arr) {
  285. var str = "";
  286. for (var i = 0; i < arr.length; i++) {
  287. str += String.fromCharCode(arr[i]);
  288. }
  289. return str;
  290. }
  291. function stringToByte(str) {
  292. var arr = [];
  293. for (var i = 0; i< str.length; i++) {
  294. arr.push(str.charCodeAt(i));
  295. }
  296. return new Uint8Array(arr);
  297. }