<?PHP
###################################################################################################
## Main function for message encryption if key is 8chrs it encrypts DES, if 24chrs or more, 3DES ##
###################################################################################################


## This takes care of bit-shuffling, and enhances php to accept zero fill shift right bitwise operator >>> ## 
function zeroFill($a$b) { 
$z hexdec(80000000);
$z = (int)$z;
$a = (int)$a;
$b = (int)$b;
if (
$z $a) { 
 
$a >>= 1
 
$a &= (~ $z); 
 
$a |= 0x40000000
 
$a >>= ($b-1); 
} else { 
 
$a >>= $b

return 
$a
}

function 
TripleDES ($key$message$encrypt$mode$iv) {
  
# declaring this locally speeds things up a bit
  
$spfunction1 = 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);
  
$spfunction2 = 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);
  
$spfunction3 = 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);
  
$spfunction4 = 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);
  
$spfunction5 = 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);
  
$spfunction6 = 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);
  
$spfunction7 = 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);
  
$spfunction8 = 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);

  
#create the 16 or 48 subkeys we will need
  
$keys des_createKeys($key);
    
$keysize count($keys);
    
$m=0;
    
$i=0;
    
$temp=0;
    
$temp2=0;
    
$right1=0;
    
$right2=0;
    
$left=0;
    
$right=0;
    
$looping=0;
    
$cbcleft=0;
    
$cbcleft2=0;
    
$cbcright=0;
    
$cbcright2=0;
    
$endloop=0;
    
$loopinc=0;
    
$result=0;
    
$tempresult=0;
  
$len strlen($message);
    
$chunk 0;
  
#set up the loops for single and triple des
  
$iterations count($keys) == 32 9#single or triple des
  
if ($iterations == 3) {$looping $encrypt ? array(0322) : array(30, -2, -2);}
  else {
$looping $encrypt ? array(03226230, -264962) : array(9462, -23264230, -2, -2);}

  
$message .= "\0\0\0\0\0\0\0\0"#pad the message out with null bytes
  #store the result here
  
$result "";
  
$tempresult "";

  if (
$mode == 1) { #CBC mode
    
$cbcleft = (ord(substr($iv,$m++,1)) << 24) | (ord(substr($iv,$m++,1)) << 16) | (ord(substr($iv,$m++,1)) << 8) | ord(substr($iv,$m++,1));
    
$cbcright = (ord(substr($iv,$m++,1)) << 24) | (ord(substr($iv,$m++,1)) << 16) | (ord(substr($iv,$m++,1)) << 8) | ord(substr($iv,$m++,1));
    
$m=0;
    }

  
#loop through each 64 bit chunk of the message
  
while ($m $len) {
    
$left = (ord(substr($message,$m++,1)) << 24) | (ord(substr($message,$m++,1)) << 16) | (ord(substr($message,$m++,1)) << 8) | ord(substr($message,$m++,1));
    
$right = (ord(substr($message,$m++,1)) << 24) | (ord(substr($message,$m++,1)) << 16) | (ord(substr($message,$m++,1)) << 8) | ord(substr($message,$m++,1));
        
#for Cipher Block Chaining mode, xor the message with the previous result
    
if ($mode == 1) { 
            if (
$encrypt) {
                
$left ^= $cbcleft;
                
$right ^= $cbcright;
                } else {
                
$cbcleft2 $cbcleft
                
$cbcright2 $cbcright
                
$cbcleft $left;
                
$cbcright $right;
            }
        }

    
#first each 64 but chunk of the message must be permuted according to IP
    
$temp = ((zeroFill($left4)) ^ $right) & 0x0f0f0f0f;
        
$right ^= $temp$left ^= ($temp << 4);
    
$temp = ((zeroFill($left16)) ^ $right) & 0x0000ffff;
        
$right ^= $temp$left ^= ($temp << 16);
    
$temp = ((zeroFill($right2)) ^ $left) & 0x33333333;
        
$left ^= $temp$right ^= ($temp << 2);
    
$temp = ((zeroFill($right8)) ^ $left) & 0x00ff00ff;
        
$left ^= $temp$right ^= ($temp << 8);
    
$temp = ((zeroFill($left1)) ^ $right) & 0x55555555;
        
$right ^= $temp$left ^= ($temp << 1);
        
    
$left = (($left << 1) | (zeroFill($left31))); 
    
$right = (($right << 1) | (zeroFill($right31))); 
        
#do this either 1 or 3 times for each chunk of the message
    
for ($j=0$j<$iterations$j+=3) {
      
$endloop =$looping[$j+1];
            
$loopinc =$looping[$j+2]; #now go through and perform the encryption or decryption  
      
for ($i=$looping[$j]; $i!=$endloop$i+=$loopinc) { #for efficiency
              
$right1 =$right $keys[$i]; 
        
$right2 =((zeroFill($right4)) | ($right << 28)) ^ $keys[$i+1];
        
#the result is attained by passing these bytes through the S selection functions
        
$temp $left;
        
$left $right;
        
$right $temp ^ ($spfunction2[(zeroFill($right124)) & 0x3f] | $spfunction4[($right1 >> 16) & 0x3f]
              | 
$spfunction6[(zeroFill($right18)) & 0x3f] | $spfunction8[$right1 0x3f]
              | 
$spfunction1[(zeroFill($right224)) & 0x3f] | $spfunction3[(zeroFill($right216)) & 0x3f]
              | 
$spfunction5[(zeroFill($right28)) & 0x3f] | $spfunction7[$right2 0x3f]);
      }
      
$temp $left;
            
$left $right;
            
$right $temp#unreverse left and right
        
#for either 1 or 3 iterations
        
    #move then each one bit to the right
    
$left = ((zeroFill($left1)) | ($left << 31)); 
    
$right = ((zeroFill($right1)) | ($right << 31)); 
        
    
#now perform IP-1, which is IP in the opposite direction
    
$temp = ((zeroFill($left1)) ^ $right) & 0x55555555$right ^= $temp$left ^= ($temp << 1);
    
$temp = ((zeroFill($right8)) ^ $left) & 0x00ff00ff$left ^= $temp$right ^= ($temp << 8);
    
$temp = ((zeroFill($right2)) ^ $left) & 0x33333333$left ^= $temp$right ^= ($temp << 2);
    
$temp = ((zeroFill($left16)) ^ $right) & 0x0000ffff$right ^= $temp$left ^= ($temp << 16);
    
$temp = ((zeroFill($left4)) ^ $right) & 0x0f0f0f0f$right ^= $temp$left ^= ($temp << 4);
        
    
#for Cipher Block Chaining mode, xor the message with the previous result
    
if ($mode == 1) {
            if (
$encrypt) {
                
$cbcleft $left
                
$cbcright $right;
                } else {
                
$left ^= $cbcleft2;
                
$right ^= $cbcright2;
            }
        }
        
$tempresult .= chr(zeroFill($left24)) . chr((zeroFill($left16)) & 0xff) . chr((zeroFill($left8)) & 0xff) . chr($left 0xff) . chr(zeroFill($right24)) . chr((zeroFill($right16)) & 0xff) . chr((zeroFill($right8)) & 0xff) . chr($right 0xff);
        
$chunk += 8;
    if (
$chunk == 512) {$result .= $tempresult$tempresult ""$chunk 0;}
  } 
#for every 8 characters, or 64 bits in the message

  #return the result as an array
  
return $result $tempresult;
#end of des

###########################################################
## Function for creating keys for the TripleDES-function ##
###########################################################
function des_createKeys ($key) {
  
# declaring this locally speeds things up a bit ##
  
$pc2bytes0  = array(0,0x4,0x20000000,0x20000004,0x10000,0x10004,0x20010000,0x20010004,0x200,0x204,0x20000200,0x20000204,0x10200,0x10204,0x20010200,0x20010204);
  
$pc2bytes1  = array(0,0x1,0x100000,0x100001,0x4000000,0x4000001,0x4100000,0x4100001,0x100,0x101,0x100100,0x100101,0x4000100,0x4000101,0x4100100,0x4100101);
  
$pc2bytes2  = array(0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808,0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808);
  
$pc2bytes3  = array(0,0x200000,0x8000000,0x8200000,0x2000,0x202000,0x8002000,0x8202000,0x20000,0x220000,0x8020000,0x8220000,0x22000,0x222000,0x8022000,0x8222000);
  
$pc2bytes4  = array(0,0x40000,0x10,0x40010,0,0x40000,0x10,0x40010,0x1000,0x41000,0x1010,0x41010,0x1000,0x41000,0x1010,0x41010);
  
$pc2bytes5  = array(0,0x400,0x20,0x420,0,0x400,0x20,0x420,0x2000000,0x2000400,0x2000020,0x2000420,0x2000000,0x2000400,0x2000020,0x2000420);
  
$pc2bytes6  = array(0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002,0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002);
  
$pc2bytes7  = array(0,0x10000,0x800,0x10800,0x20000000,0x20010000,0x20000800,0x20010800,0x20000,0x30000,0x20800,0x30800,0x20020000,0x20030000,0x20020800,0x20030800);
  
$pc2bytes8  = array(0,0x40000,0,0x40000,0x2,0x40002,0x2,0x40002,0x2000000,0x2040000,0x2000000,0x2040000,0x2000002,0x2040002,0x2000002,0x2040002);
  
$pc2bytes9  = array(0,0x10000000,0x8,0x10000008,0,0x10000000,0x8,0x10000008,0x400,0x10000400,0x408,0x10000408,0x400,0x10000400,0x408,0x10000408);
  
$pc2bytes10 = array(0,0x20,0,0x20,0x100000,0x100020,0x100000,0x100020,0x2000,0x2020,0x2000,0x2020,0x102000,0x102020,0x102000,0x102020);
  
$pc2bytes11 = array(0,0x1000000,0x200,0x1000200,0x200000,0x1200000,0x200200,0x1200200,0x4000000,0x5000000,0x4000200,0x5000200,0x4200000,0x5200000,0x4200200,0x5200200);
  
$pc2bytes12 = array(0,0x1000,0x8000000,0x8001000,0x80000,0x81000,0x8080000,0x8081000,0x10,0x1010,0x8000010,0x8001010,0x80010,0x81010,0x8080010,0x8081010);
  
$pc2bytes13 = array(0,0x4,0x100,0x104,0,0x4,0x100,0x104,0x1,0x5,0x101,0x105,0x1,0x5,0x101,0x105);
  
# how many iterations (1 for des, 3 for triple des) ##
  
$iterations strlen($key) >= 24 1;
    
# creates the php eq of the array to hold the keys for return ##
    
$keynum = (32 $iterations);
    
$keystr "";
    for(
$e=0;$e<$keynum;$e++) {
    
$keystr .= $e.",";
    }
    
$keystr substr("$keystr"0, -1);
    
$keys array_keys(explode(","$keystr));
    
# now define the left shifts which need to be done ##
    
$shifts = array(0011111101111110);
    
$m=0;
    
$n=0;
    
$left=0;
    
$right=0;
    for (
$j=0$j<$iterations$j++) { #either 1 or 3 iterations
        ## Pilfer the ascii-values using ord() ##
        
$left =(ord(substr($key,$m++,1)) << 24) | (ord(substr($key,$m++,1)) << 16) | (ord(substr($key,$m++,1)) << 8) | ord(substr($key,$m++,1));
    
$right = (ord(substr($key,$m++,1)) << 24) | (ord(substr($key,$m++,1)) << 16) | (ord(substr($key,$m++,1)) << 8) | ord(substr($key,$m++,1));
        
## The zerofill() function enhances php to accept zero fill shift right bitwise operator (>>>) ##
         
$temp = ((zeroFill($left4)) ^  $right) & 0x0f0f0f0f$right ^= $temp$left  ^= ($temp << 4);
    
$temp = ((zeroFill($right, -16)) ^ $left) & 0x0000ffff$left ^=  $temp$right ^= ($temp << -16);
    
$temp = ((zeroFill($left2)) ^  $right) & 0x33333333$right ^= $temp$left  ^= ($temp << 2);
    
$temp = ((zeroFill($right, -16)) ^ $left) & 0x0000ffff$left ^=  $temp$right ^= ($temp << 16);
    
$temp = ((zeroFill($left1)) ^  $right) & 0x55555555$right ^= $temp$left  ^= ($temp << 1);
    
$temp = ((zeroFill($right8)) ^  $left) & 0x00ff00ff$left ^=  $temp$right ^= ($temp << 8);
    
$temp = ((zeroFill($left1)) ^  $right) & 0x55555555$right ^= $temp$left  ^= ($temp << 1);
        
#the right side needs to be shifted and to get the last four bits of the left side
    
$temp = ($left << 8) | ((zeroFill($right20)) & 0x000000f0);
        
    
#left needs to be put upside down
    
$left = ($right << 24) | (($right << 8) & 0xff0000) | ((zeroFill($right8)) & (int)0xff00) | ((zeroFill($right24)) & 0xf0);
        
$right $temp;
      
#now go through and perform these shifts on the left and right keys
         
for ($i=0$i sizeof($shifts); $i++) {
          
#shift the keys either one or two bits to the left
      
if ($shifts[$i]) {
              
$left = ($left << 2) | (zeroFill($left26)); 
        
$right = ($right << 2) | (zeroFill($right26));
                } else {
                 
$left = ($left << 1) | (zeroFill($left27)); 
        
$right = ($right << 1) | (zeroFill($right27));
            }
      
$left &= 0xfffffff0;
            
$right &= 0xfffffff0;
            
      
#now apply PC-2, in such a way that E is easier when encrypting or decrypting
      #this conversion will look like PC-2 except only the last 6 bits of each byte are used
      #rather than 48 consecutive bits and the order of lines will be according to 
      #how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7
      
$lefttemp $pc2bytes0[zeroFill($left28)] | $pc2bytes1[(zeroFill($left24)) & 0xf] | $pc2bytes2[(zeroFill($left20)) & 0xf] | $pc2bytes3[(zeroFill($left16)) & 0xf] | $pc2bytes4[(zeroFill($left12)) & 0xf] | $pc2bytes5[(zeroFill($left8)) & 0xf] | $pc2bytes6[(zeroFill($left4)) & (int)0xf];
      
$righttemp $pc2bytes7[zeroFill($right28)] | $pc2bytes8[(zeroFill($right24)) & 0xf] | $pc2bytes9[(zeroFill($right20)) & 0xf] | $pc2bytes10[(zeroFill($right16)) & 0xf] | $pc2bytes11[(zeroFill($right12)) & 0xf] | $pc2bytes12[(zeroFill($right8)) & 0xf] | $pc2bytes13[(zeroFill($right4)) & 0xf];
         
$temp = ((zeroFill($righttemp16)) ^ $lefttemp) & 0x0000ffff
      
$keys[$n++] = $lefttemp $temp
            
            
$keys[$n++] = $righttemp ^ ($temp << 16);
        }
    } 
#for each iterations
  #return the keys we've created
    
return $keys;
 
#end of des_createKeys

#################################################
## Function for making hex out of the bin-gore ##
#################################################
function printHex ($s) {
  
$r "0x";
    
$num count($s);
  
$hexes= array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
  for (
$i=0$i<strlen($s); $i++) {
    
$r.=$hexes[ord(substr($s,$i,1)) >> 4] . $hexes[ord(substr($s,$i,1)) & 0xf];
    }
  return 
$r;
}

############################################
## Coverts the submit hash to binary data ##
############################################
function hexToString ($h) {
  
$r "";
  for (
$i= (substr($h,02)== "0x") ? 0$i<strlen($h); $i+=2) {
    
$r .= chr(base_convert(substr($h$i2), 1610));
    }
  return 
$r;
}

?>