Esempio n. 1
0
 /**
  * Setup the performance-optimized function for de/encrypt()
  *
  * @see Base::_setupInlineCrypt()
  * @access private
  */
 function _setupInlineCrypt()
 {
     $lambda_functions =& DES::_getLambdaFunctions();
     // Engine configuration for:
     // -  DES ($des_rounds == 1) or
     // - 3DES ($des_rounds == 3)
     $des_rounds = $this->des_rounds;
     // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
     // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one
     $gen_hi_opt_code = (bool) (count($lambda_functions) < 10);
     // Generation of a uniqe hash for our generated code
     switch (true) {
         case $gen_hi_opt_code:
             // For hi-optimized code, we create for each combination of
             // $mode, $des_rounds and $this->key its own encrypt/decrypt function.
             $code_hash = md5(str_pad("DES, {$des_rounds}, {$this->mode}, ", 32, "") . $this->key);
             break;
         default:
             // After max 10 hi-optimized functions, we create generic
             // (still very fast.. but not ultra) functions for each $mode/$des_rounds
             // Currently 2 * 5 generic functions will be then max. possible.
             $code_hash = "DES, {$des_rounds}, {$this->mode}";
     }
     // Is there a re-usable $lambda_functions in there? If not, we have to create it.
     if (!isset($lambda_functions[$code_hash])) {
         // Init code for both, encrypt and decrypt.
         $init_crypt = 'static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
             if (!$sbox1) {
                 $sbox1 = array_map("intval", $self->sbox1);
                 $sbox2 = array_map("intval", $self->sbox2);
                 $sbox3 = array_map("intval", $self->sbox3);
                 $sbox4 = array_map("intval", $self->sbox4);
                 $sbox5 = array_map("intval", $self->sbox5);
                 $sbox6 = array_map("intval", $self->sbox6);
                 $sbox7 = array_map("intval", $self->sbox7);
                 $sbox8 = array_map("intval", $self->sbox8);' . '
                 for ($i = 0; $i < 256; ++$i) {
                     $shuffleip[]    =  $self->shuffle[$self->ipmap[$i]];
                     $shuffleinvip[] =  $self->shuffle[$self->invipmap[$i]];
                 }
             }
         ';
         switch (true) {
             case $gen_hi_opt_code:
                 // In Hi-optimized code mode, we use our [3]DES key schedule as hardcoded integers.
                 // No futher initialisation of the $keys schedule is necessary.
                 // That is the extra performance boost.
                 $k = array(CRYPT_DES_ENCRYPT => $this->keys[CRYPT_DES_ENCRYPT], CRYPT_DES_DECRYPT => $this->keys[CRYPT_DES_DECRYPT]);
                 $init_encrypt = '';
                 $init_decrypt = '';
                 break;
             default:
                 // In generic optimized code mode, we have to use, as the best compromise [currently],
                 // our key schedule as $ke/$kd arrays. (with hardcoded indexes...)
                 $k = array(CRYPT_DES_ENCRYPT => array(), CRYPT_DES_DECRYPT => array());
                 for ($i = 0, $c = count($this->keys[CRYPT_DES_ENCRYPT]); $i < $c; ++$i) {
                     $k[CRYPT_DES_ENCRYPT][$i] = '$ke[' . $i . ']';
                     $k[CRYPT_DES_DECRYPT][$i] = '$kd[' . $i . ']';
                 }
                 $init_encrypt = '$ke = $self->keys[CRYPT_DES_ENCRYPT];';
                 $init_decrypt = '$kd = $self->keys[CRYPT_DES_DECRYPT];';
                 break;
         }
         // Creating code for en- and decryption.
         $crypt_block = array();
         foreach (array(CRYPT_DES_ENCRYPT, CRYPT_DES_DECRYPT) as $c) {
             /* Do the initial IP permutation. */
             $crypt_block[$c] = '
                 $in = unpack("N*", $in);
                 $l  = $in[1];
                 $r  = $in[2];
                 $in = unpack("N*",
                     ($shuffleip[ $r        & 0xFF] & "\\x80\\x80\\x80\\x80\\x80\\x80\\x80\\x80") |
                     ($shuffleip[($r >>  8) & 0xFF] & "\\x40\\x40\\x40\\x40\\x40\\x40\\x40\\x40") |
                     ($shuffleip[($r >> 16) & 0xFF] & "\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20") |
                     ($shuffleip[($r >> 24) & 0xFF] & "\\x10\\x10\\x10\\x10\\x10\\x10\\x10\\x10") |
                     ($shuffleip[ $l        & 0xFF] & "\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08") |
                     ($shuffleip[($l >>  8) & 0xFF] & "\\x04\\x04\\x04\\x04\\x04\\x04\\x04\\x04") |
                     ($shuffleip[($l >> 16) & 0xFF] & "\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02") |
                     ($shuffleip[($l >> 24) & 0xFF] & "\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01")
                 );
                 ' . '
                 $l = $in[1];
                 $r = $in[2];
             ';
             $l = '$l';
             $r = '$r';
             // Perform DES or 3DES.
             for ($ki = -1, $des_round = 0; $des_round < $des_rounds; ++$des_round) {
                 // Perform the 16 steps.
                 for ($i = 0; $i < 16; ++$i) {
                     // start of "the Feistel (F) function" - see the following URL:
                     // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
                     // Merge key schedule.
                     $crypt_block[$c] .= '
                         $b1 = ((' . $r . ' >>  3) & 0x1FFFFFFF)  ^ (' . $r . ' << 29) ^ ' . $k[$c][++$ki] . ';
                         $b2 = ((' . $r . ' >> 31) & 0x00000001)  ^ (' . $r . ' <<  1) ^ ' . $k[$c][++$ki] . ';' . $l . ' = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^
                                  $sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^
                                  $sbox5[($b1 >>  8) & 0x3F] ^ $sbox6[($b2 >>  8) & 0x3F] ^
                                  $sbox7[ $b1        & 0x3F] ^ $sbox8[ $b2        & 0x3F] ^ ' . $l . ';
                     ';
                     // end of "the Feistel (F) function"
                     // swap L & R
                     list($l, $r) = array($r, $l);
                 }
                 list($l, $r) = array($r, $l);
             }
             // Perform the inverse IP permutation.
             $crypt_block[$c] .= '$in =
                 ($shuffleinvip[($l >> 24) & 0xFF] & "\\x80\\x80\\x80\\x80\\x80\\x80\\x80\\x80") |
                 ($shuffleinvip[($r >> 24) & 0xFF] & "\\x40\\x40\\x40\\x40\\x40\\x40\\x40\\x40") |
                 ($shuffleinvip[($l >> 16) & 0xFF] & "\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20") |
                 ($shuffleinvip[($r >> 16) & 0xFF] & "\\x10\\x10\\x10\\x10\\x10\\x10\\x10\\x10") |
                 ($shuffleinvip[($l >>  8) & 0xFF] & "\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08") |
                 ($shuffleinvip[($r >>  8) & 0xFF] & "\\x04\\x04\\x04\\x04\\x04\\x04\\x04\\x04") |
                 ($shuffleinvip[ $l        & 0xFF] & "\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02") |
                 ($shuffleinvip[ $r        & 0xFF] & "\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01");
             ';
         }
         // Creates the inline-crypt function
         $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(array('init_crypt' => $init_crypt, 'init_encrypt' => $init_encrypt, 'init_decrypt' => $init_decrypt, 'encrypt_block' => $crypt_block[CRYPT_DES_ENCRYPT], 'decrypt_block' => $crypt_block[CRYPT_DES_DECRYPT]));
     }
     // Set the inline-crypt function as callback in: $this->inline_crypt
     $this->inline_crypt = $lambda_functions[$code_hash];
 }