3DES CB加密动态密钥

时间:2015-04-13 16:54:09

标签: php mcrypt 3des

一个人告诉我使用根据以下算法生成的动态密钥来加密数据

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='0123456789ABCDEF'

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

为了实现算法,我写了这个类函数

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

        $staticKey  =  
        $mode       = MCRYPT_MODE_CBC;
        $ivi        = '0123456789ABCDEF';
        $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==

任何提示?

1 个答案:

答案 0 :(得分:0)

在某处搜索后,我发现3DES想要一个192位的密钥,而php的{​​{1}}在某种程度上不会那么神奇:你必须自己填充密钥!这两个函数适用于问题的示例:

mcrypt