Advertisement
Guest User

DES in JS

a guest
Dec 18th, 2011
384
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //-----------------------------------------------------------------------------
  2. // Start of code NOT solely copyright Dr. Net!
  3. //-----------------------------------------------------------------------------
  4.  
  5. /*
  6. Original:
  7.  
  8. Paul Tero, July 2001
  9. http://www.shopable.co.uk/des.html
  10.  
  11. Optimised for performance with large blocks by Michael Hayworth, November 2001
  12. http://www.netdealing.com
  13.  
  14. THIS SOFTWARE IS PROVIDED "AS IS" AND
  15. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  18. FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20. OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21. HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23. OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24. SUCH DAMAGE.
  25.  
  26. Minor modifications and Puzzle wrapper:
  27.     (c) 2007 Eugen Rieck
  28. */
  29.  
  30. function DES() {
  31.   this.Key='';
  32. }
  33.  
  34. DES.prototype.Encrypt=function(message) {
  35.   return this.des(this.Key,message,1,0,'');
  36. }
  37.  
  38. DES.prototype.Decrypt=function(message) {
  39.   return this.des(this.Key,message,0,0,'');
  40. }
  41.  
  42. //this takes the key, the message, and whether to encrypt or decrypt
  43. DES.prototype.des=function(key, message, encrypt, mode, iv) {
  44.   //declaring this locally speeds things up a bit
  45.   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);
  46.   var spfunction2 = new Array (0x80108020,0x80008000,0x8000,0x108020,0x100000,0x20,0x80100020,0x80008020,0x80000020,0x80108020,0x80108000,0x80000000,0x80008000,0x100000,0x20,0x80100020,0x108000,0x100020,0x80008020,0,0x80000000,0x8000,0x108020,0x80100000,0x100020,0x80000020,0,0x108000,0x8020,0x80108000,0x80100000,0x8020,0,0x108020,0x80100020,0x100000,0x80008020,0x80100000,0x80108000,0x8000,0x80100000,0x80008000,0x20,0x80108020,0x108020,0x20,0x8000,0x80000000,0x8020,0x80108000,0x100000,0x80000020,0x100020,0x80008020,0x80000020,0x100020,0x108000,0,0x80008000,0x8020,0x80000000,0x80100020,0x80108020,0x108000);
  47.   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);
  48.   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);
  49.   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);
  50.   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);
  51.   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);
  52.   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);
  53.  
  54.   //create the 16 or 48 subkeys we will need
  55.   var keys = this.des_createKeys (key);
  56.   var m=0, i, j, temp, temp2, right1, right2, left, right, looping;
  57.   var cbcleft, cbcleft2, cbcright, cbcright2
  58.   var endloop, loopinc;
  59.   var len = message.length;
  60.   var chunk = 0;
  61.   //set up the loops for single and triple des
  62.   var iterations = keys.length == 32 ? 3 : 9; //single or triple des
  63.   if (iterations == 3) {looping = encrypt ? new Array (0, 32, 2) : new Array (30, -2, -2);}
  64.   else {looping = encrypt ? new Array (0, 32, 2, 62, 30, -2, 64, 96, 2) : new Array (94, 62, -2, 32, 64, 2, 30, -2, -2);}
  65.  
  66.   message += "\0\0\0\0\0\0\0\0"; //pad the message out with null bytes
  67.   //store the result here
  68.   result = "";
  69.   tempresult = "";
  70.  
  71.   if (mode == 1) { //CBC mode
  72.     cbcleft = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++);
  73.     cbcright = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++);
  74.     m=0;
  75.   }
  76.  
  77.   //loop through each 64 bit chunk of the message
  78.   while (m < len) {
  79.     left = (message.charCodeAt(m++) << 24) | (message.charCodeAt(m++) << 16) | (message.charCodeAt(m++) << 8) | message.charCodeAt(m++);
  80.     right = (message.charCodeAt(m++) << 24) | (message.charCodeAt(m++) << 16) | (message.charCodeAt(m++) << 8) | message.charCodeAt(m++);
  81.  
  82.     //for Cipher Block Chaining mode, xor the message with the previous result
  83.     if (mode == 1) {if (encrypt) {left ^= cbcleft; right ^= cbcright;} else {cbcleft2 = cbcleft; cbcright2 = cbcright; cbcleft = left; cbcright = right;}}
  84.  
  85.     //first each 64 but chunk of the message must be permuted according to IP
  86.     temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
  87.     temp = ((left >>> 16) ^ right) & 0x0000ffff; right ^= temp; left ^= (temp << 16);
  88.     temp = ((right >>> 2) ^ left) & 0x33333333; left ^= temp; right ^= (temp << 2);
  89.     temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
  90.     temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
  91.  
  92.     left = ((left << 1) | (left >>> 31));
  93.     right = ((right << 1) | (right >>> 31));
  94.  
  95.     //do this either 1 or 3 times for each chunk of the message
  96.     for (j=0; j<iterations; j+=3) {
  97.       endloop = looping[j+1];
  98.       loopinc = looping[j+2];
  99.       //now go through and perform the encryption or decryption  
  100.       for (i=looping[j]; i!=endloop; i+=loopinc) { //for efficiency
  101.         right1 = right ^ keys[i];
  102.         right2 = ((right >>> 4) | (right << 28)) ^ keys[i+1];
  103.         //the result is attained by passing these bytes through the S selection functions
  104.         temp = left;
  105.         left = right;
  106.         right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f]
  107.               | spfunction6[(right1 >>>  8) & 0x3f] | spfunction8[right1 & 0x3f]
  108.               | spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & 0x3f]
  109.               | spfunction5[(right2 >>>  8) & 0x3f] | spfunction7[right2 & 0x3f]);
  110.       }
  111.       temp = left; left = right; right = temp; //unreverse left and right
  112.     } //for either 1 or 3 iterations
  113.  
  114.     //move then each one bit to the right
  115.     left = ((left >>> 1) | (left << 31));
  116.     right = ((right >>> 1) | (right << 31));
  117.  
  118.     //now perform IP-1, which is IP in the opposite direction
  119.     temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
  120.     temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
  121.     temp = ((right >>> 2) ^ left) & 0x33333333; left ^= temp; right ^= (temp << 2);
  122.     temp = ((left >>> 16) ^ right) & 0x0000ffff; right ^= temp; left ^= (temp << 16);
  123.     temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
  124.  
  125.     //for Cipher Block Chaining mode, xor the message with the previous result
  126.     if (mode == 1) {if (encrypt) {cbcleft = left; cbcright = right;} else {left ^= cbcleft2; right ^= cbcright2;}}
  127.     tempresult += String.fromCharCode ((left>>>24), ((left>>>16) & 0xff), ((left>>>8) & 0xff), (left & 0xff), (right>>>24), ((right>>>16) & 0xff), ((right>>>8) & 0xff), (right & 0xff));
  128.  
  129.     chunk += 8;
  130.     if (chunk == 512) {result += tempresult; tempresult = ""; chunk = 0;}
  131.   } //for every 8 characters, or 64 bits in the message
  132.  
  133.   //return the result as an array
  134.   return result + tempresult;
  135. } //end of des
  136.  
  137.  
  138.  
  139. //des_createKeys
  140. //this takes as input a 64 bit key (even though only 56 bits are used)
  141. //as an array of 2 integers, and returns 16 48 bit keys
  142. DES.prototype.des_createKeys=function(key) {
  143.   //declaring this locally speeds things up a bit
  144.   pc2bytes0  = new Array (0,0x4,0x20000000,0x20000004,0x10000,0x10004,0x20010000,0x20010004,0x200,0x204,0x20000200,0x20000204,0x10200,0x10204,0x20010200,0x20010204);
  145.   pc2bytes1  = new Array (0,0x1,0x100000,0x100001,0x4000000,0x4000001,0x4100000,0x4100001,0x100,0x101,0x100100,0x100101,0x4000100,0x4000101,0x4100100,0x4100101);
  146.   pc2bytes2  = new Array (0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808,0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808);
  147.   pc2bytes3  = new Array (0,0x200000,0x8000000,0x8200000,0x2000,0x202000,0x8002000,0x8202000,0x20000,0x220000,0x8020000,0x8220000,0x22000,0x222000,0x8022000,0x8222000);
  148.   pc2bytes4  = new Array (0,0x40000,0x10,0x40010,0,0x40000,0x10,0x40010,0x1000,0x41000,0x1010,0x41010,0x1000,0x41000,0x1010,0x41010);
  149.   pc2bytes5  = new Array (0,0x400,0x20,0x420,0,0x400,0x20,0x420,0x2000000,0x2000400,0x2000020,0x2000420,0x2000000,0x2000400,0x2000020,0x2000420);
  150.   pc2bytes6  = new Array (0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002,0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002);
  151.   pc2bytes7  = new Array (0,0x10000,0x800,0x10800,0x20000000,0x20010000,0x20000800,0x20010800,0x20000,0x30000,0x20800,0x30800,0x20020000,0x20030000,0x20020800,0x20030800);
  152.   pc2bytes8  = new Array (0,0x40000,0,0x40000,0x2,0x40002,0x2,0x40002,0x2000000,0x2040000,0x2000000,0x2040000,0x2000002,0x2040002,0x2000002,0x2040002);
  153.   pc2bytes9  = new Array (0,0x10000000,0x8,0x10000008,0,0x10000000,0x8,0x10000008,0x400,0x10000400,0x408,0x10000408,0x400,0x10000400,0x408,0x10000408);
  154.   pc2bytes10 = new Array (0,0x20,0,0x20,0x100000,0x100020,0x100000,0x100020,0x2000,0x2020,0x2000,0x2020,0x102000,0x102020,0x102000,0x102020);
  155.   pc2bytes11 = new Array (0,0x1000000,0x200,0x1000200,0x200000,0x1200000,0x200200,0x1200200,0x4000000,0x5000000,0x4000200,0x5000200,0x4200000,0x5200000,0x4200200,0x5200200);
  156.   pc2bytes12 = new Array (0,0x1000,0x8000000,0x8001000,0x80000,0x81000,0x8080000,0x8081000,0x10,0x1010,0x8000010,0x8001010,0x80010,0x81010,0x8080010,0x8081010);
  157.   pc2bytes13 = new Array (0,0x4,0x100,0x104,0,0x4,0x100,0x104,0x1,0x5,0x101,0x105,0x1,0x5,0x101,0x105);
  158.  
  159.   //how many iterations (1 for des, 3 for triple des)
  160.   var iterations = key.length >= 24 ? 3 : 1;
  161.   //stores the return keys
  162.   var keys = new Array (32 * iterations);
  163.   //now define the left shifts which need to be done
  164.   var shifts = new Array (0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0);
  165.   //other variables
  166.   var lefttemp, righttemp, m=0, n=0, temp;
  167.  
  168.   for (var j=0; j<iterations; j++) { //either 1 or 3 iterations
  169.     left = (key.charCodeAt(m++) << 24) | (key.charCodeAt(m++) << 16) | (key.charCodeAt(m++) << 8) | key.charCodeAt(m++);
  170.     right = (key.charCodeAt(m++) << 24) | (key.charCodeAt(m++) << 16) | (key.charCodeAt(m++) << 8) | key.charCodeAt(m++);
  171.  
  172.     temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
  173.     temp = ((right >>> -16) ^ left) & 0x0000ffff; left ^= temp; right ^= (temp << -16);
  174.     temp = ((left >>> 2) ^ right) & 0x33333333; right ^= temp; left ^= (temp << 2);
  175.     temp = ((right >>> -16) ^ left) & 0x0000ffff; left ^= temp; right ^= (temp << -16);
  176.     temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
  177.     temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
  178.     temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
  179.  
  180.     //the right side needs to be shifted and to get the last four bits of the left side
  181.     temp = (left << 8) | ((right >>> 20) & 0x000000f0);
  182.     //left needs to be put upside down
  183.     left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0);
  184.     right = temp;
  185.  
  186.     //now go through and perform these shifts on the left and right keys
  187.     for (i=0; i < shifts.length; i++) {
  188.       //shift the keys either one or two bits to the left
  189.       if (shifts[i]) {left = (left << 2) | (left >>> 26); right = (right << 2) | (right >>> 26);}
  190.       else {left = (left << 1) | (left >>> 27); right = (right << 1) | (right >>> 27);}
  191.       left &= 0xfffffff0; right &= 0xfffffff0;
  192.  
  193.       //now apply PC-2, in such a way that E is easier when encrypting or decrypting
  194.       //this conversion will look like PC-2 except only the last 6 bits of each byte are used
  195.       //rather than 48 consecutive bits and the order of lines will be according to
  196.       //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7
  197.       lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf]
  198.               | pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[(left >>> 16) & 0xf]
  199.               | pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf]
  200.               | pc2bytes6[(left >>> 4) & 0xf];
  201.       righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf]
  202.                 | pc2bytes9[(right >>> 20) & 0xf] | pc2bytes10[(right >>> 16) & 0xf]
  203.                 | pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf]
  204.                 | pc2bytes13[(right >>> 4) & 0xf];
  205.       temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff;
  206.       keys[n++] = lefttemp ^ temp; keys[n++] = righttemp ^ (temp << 16);
  207.     }
  208.   } //for each iterations
  209.   //return the keys we've created
  210.   return keys;
  211. } //end of des_createKeys
  212.  
  213.  
  214. ////////////////////////////// TEST //////////////////////////////
  215. //printHexArray
  216. function printHex (s) {
  217.   var r = "0x";
  218.   var hexes = new Array ("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
  219.   for (var i=0; i<s.length; i++) {r += hexes [s.charCodeAt(i) >> 4] + hexes [s.charCodeAt(i) & 0xf];}
  220.   return r;
  221. }
  222.  
  223. function unHex(s)
  224. {
  225.   var r = "";
  226.   for (var i=2; i<s.length;i+=2) {
  227.     x1 = s.charCodeAt(i);
  228.     x1 = x1 >= 48 && x1 < 58 ? x1 - 48 : x1 - 97 + 10;
  229.     x2 = s.charCodeAt(i+1);
  230.     x2 = x2 >= 48 && x2 < 58 ? x2 - 48 : x2 - 97 + 10;
  231.     r += String.fromCharCode (((x1 << 4) & 0xF0) | (x2 & 0x0F));   
  232.   }
  233.   return r;
  234. }
  235.  
  236. //var key = "this is a 24 byte key !!";
  237. //var message = "This is a test message";
  238. //var ciphertext = des (key, message, 1, 0);
  239. //document.writeln ("DES Test: " + printHex (ciphertext));
  240. //-----------------------------------------------------------------------------
  241. // End of code NOT solely copyright Dr. Net!
  242. //-----------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement