2015-04-13 9 views
0

Мужик сказал мне, чтобы шифровать данные с помощью динамического ключа, сгенерированного в соответствии со следующим алгоритмом3DES CB Encryption Dynamic Key

timestamp = '080717032817'  
static_key = A270AE59FF7782A2EDFE1A781BAB888D0B749D265865C288 
k1 = first 5 bytes of the static key 
k2 = first 3 bytes of the integer value of the timestamp 
k3 = last 5 bytes of the static key 
k4 = last 5 bytes of the timestamp 
dynamic_key = k1k2k3k4 

Он сказал бы, что эти данные должны быть дополнены:

pad to reach a multiple of the blocksize (8byte for 3DES CBC), 

или

pad with 8 null bytes if the length of the data is already multiple of 8. 

В примере с iv='ABCDEF' он получает:

<DATA>  <TIMESTAMP> <BASE64 CRYPTED DATA> 
3408682266,080717032817,hkUIYwssDQCq0GLx/5MiZg== 

Для реализации Algo, я написал этот класс ФУНКЦИИ

private function __encrypt($data,$parameters,$time,$convert = false) 
    { 

     $staticKey = 
     $mode  = MCRYPT_MODE_CBC; 
     $ivi  = 'ABCDEF'; 
     $cipher  = MCRYPT_3DES; 
     $this->log[] = "Encrypt params: mode => {$mode}, cipher => {$cipher}, iv =>{$ivi}"; 
     $dynamicKey = 
     $iv   = pack('H*', $ivi); 
     $this->log[] = 'Initial Vector '. var_dump($iv);   
     $data = $this->__padder($data,mcrypt_get_block_size($cipher, $mode),$convert); 

     $this->log[] = ('Data After padding: ' . $data .", length (bytes):" . strlen($data)/2); 

     try { 
      $output = mcrypt_encrypt($cipher, $dynamicKey, $data, $mode,$iv); 

     } catch (Exception $ex) { 
      debug($ex->getMessage()); 
      throw new Exception($ex->getMessage()); 

     } 

     return $output; 
    } 

/** 
    * Generate a dynamic key based on a timestamp and a static key 
    * @param type $static_key 
    */ 
    private function __generateDynamicKey($static_key = '', $time) 
    { 

     $dateObj = DateTime::createFromFormat("ymdHis", $time); 


     $k[1] = substr($static_key,0, 10); 

     $k[2] = substr($time,0,6);debug($k[2]); 

     $k[3] = substr($static_key,strlen($static_key) - 10, 10);   

     $k[4] = substr($time,strlen($time)-6,6);debug($k[4]); //last 3 bytes 
     $this->log[] = ("Dynamic key =>".join("",$k). ', length in bytes=>'. strlen(pack('H*', join("",$k)))); 

     return pack('H*', join("",$k)); 

    } 
/** 
    * 
    * @param type $data 
    * @param type $blockSize 
    * @param type $convert 
    * @return string 
    */ 
    private function __padder($data,$blockSize = 8,$convert = false) 
    { 

     if ($convert) 
      $data = Generic::strToHex($data); // hex representation of the data 

     $this->log[] = 'Block size of cipher: ' .$blockSize; 
     $this->log[] = ("Hex value before padding=>".($data)); 
     //Chek if the data is padded to 16 bytes   
     $dataBytes = strlen($data)/2 ; // 1 byte = 2 Hex digits 
     $this->log[] = "Data num. of bytes " . $dataBytes; 
     $rest  = $dataBytes % $blockSize; // The num of bytes is a multiple of blockSize ? 
     $nearest = ceil($dataBytes/$blockSize) * $blockSize; 
     $output = $data; 
     if ($rest != 0) 
     { 
      $delta  = ($nearest - $dataBytes); // in bytes 
      $deltaValue = Generic::zeropad($delta, 2);    
      $this->log[] = ('padding value '.$deltaValue); 

     } 
     else 
     { 
      $this->log[] = ('Add 8 bytes of padding!'); 
      $delta  = 8; 
      $deltaValue = '00'; 

     } 

     $output = $data . str_repeat($deltaValue, $delta); 
     $this->log[] = ('Hex value after padding '. $output . ', length in bytes =>' . strlen($output)/2); 

     return $output; 
    } 

public function test($clearUserCode) 
{ 
$userCode = $this->__encrypt($clearUserCode,$provider,$time,true); //UserCode is given as string, mut be converted in hex 
     $this->log[] = ('UserCode Clear : ' . $clearUserCode . ', in hex: ' . Generic::strToHex($clearUserCode)); 
     $this->log[] = ('UserCode Crypt : ' . bin2hex($userCode)); 
     $this->log[] = ('UserCode Crypt and base64: ' . base64_encode(($userCode))); 

     $this->log[] = ('----------------------End encrypt UserCode part----------------------') ; 
} 

И, наконец, где-то

$this->test('3408682266'); 

которые дают мне другой результат:

UserCode Clear : 3408682266, in hex: 33343038363832323636 
UserCode Crypt : 9d7e195a8d85aa7d051362dfae0042c2 
UserCode Crypt and base64: nX4ZWo2Fqn0FE2LfrgBCwg== 

Любой намек?

ответ

0

После поиска в Google я обнаружил, что 3DES хочет 192-битный ключ, и каким-то образом phpmcrypt не делает это волшебным образом: вам нужно проложить ключ самостоятельно! Это две функции, которые работают на примерах вопроса:

/** 
    * Make ciphering (3DES) in pkc7 (padding with 0 or a filling value) 
    * key must bey 24 bytes (192 bits) 
    * @param type $key 
    * @param type $iv 
    * @param type $text 
    * @return type 
    */ 
    public static function encryptNET3DES($key,$iv,$text) 

    { 
     $td = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_CBC, ''); 

     // Complete the key 

     $key_add = 24-strlen($key); 
     $key  .= substr($key,0,$key_add); 


     // Padding the text 

     $block = mcrypt_get_block_size("tripledes", "cbc");     
     $len  = strlen($text);   
     $padding = $block - ($len % $block); 

     $text .= str_repeat(chr($padding),$padding);   
     mcrypt_generic_init ($td, $key, $iv); 
     $encrypt_text = mcrypt_generic ($td, $text); 
     mcrypt_generic_deinit($td); 
     mcrypt_module_close($td); 
     return $encrypt_text;  

}  
    /** 
    * Decrypt 3DES encrypted data with 24-bit key 
    * @param type $key 
    * @param type $iv 
    * @param type $text 
    * @return type 
    */ 
    public static function decryptNET3DES($key,$iv,$text) 

    { 

    $td = mcrypt_module_open (MCRYPT_3DES, "", MCRYPT_MODE_CBC, ""); 
    // Complete the key 
    $key_add = 24-strlen($key); 
    $key  .= substr($key,0,$key_add); 
    mcrypt_generic_init ($td, $key, $iv); 
    $decrypt_text = mdecrypt_generic ($td, $text); 
    mcrypt_generic_deinit($td); 
    mcrypt_module_close($td); 
    //remove the padding text 

    $block = mcrypt_get_block_size("tripledes", "cbc"); 
    $packing = ord($decrypt_text{strlen($decrypt_text) - 1}); 
    if($packing && ($packing < $block)) 
    // Get rid of padded data 
    {   
      for($P = strlen($decrypt_text) - 1; $P >= strlen($decrypt_text) - $packing; $P--)   { 
       if(ord($decrypt_text{$P}) != $packing) 
       { 
        $packing = 0; 
       } 
     } 
    } 

    $decrypt_text = substr($decrypt_text,0,strlen($decrypt_text) - $packing); 

    return $decrypt_text; 

} 
+0

Это работает только тогда, когда длина ключа <= 24. Если длина ключа> 24, размер ключа будет неправильным. – Raptor