一个人告诉我使用根据以下算法生成的动态密钥来加密数据
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==
任何提示?
答案 0 :(得分:0)
在某处搜索后,我发现3DES想要一个192位的密钥,而php
的{{1}}在某种程度上不会那么神奇:你必须自己填充密钥!这两个函数适用于问题的示例:
mcrypt