我要回过头来看一些代码[包含在这篇文章的底部],我之前为了加密而写了一些代码,我遇到了一个我无法找到解决方法的错误。每当我尝试解密我的数据时,我都会从OpenSSL中收到以下错误:
error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
我的加密功能的输出是:
$AES-256-CBC$SHA256$kJ+DIShnFOs0cGsDiVnXXMdBj1GoLYywrhz+lv3W/dk=
原始加密数据为:
00000000 90 9f 83 21 28 67 14 eb 34 70 6b 03 89 59 d7 5c |...!(g..4pk..Y.\|
00000010 c7 41 8f 51 a8 2d 8c b0 ae 1c fe 96 fd d6 fd d9 |.A.Q.-..........|
我的IV是:
00000000 d7 4f f0 ee 8d a3 b9 80 6b 18 c8 77 db f2 9b bd |.O......k..w....|
我无法弄清楚这里出了什么问题。我可以谷歌的大多数归结为“你没有从数据的开头删除IV”,但它从来没有出现过。
代码:
Class MyEncrypt {
private $method, $iv_size, $hashfunc;
public function __construct($method='AES-256-CBC', $hashfunc='SHA512') {
if( ! function_exists('openssl_encrypt') ) {
Throw new Exception('openssl_encrypt() not supported.');
} else if( ! in_array($method, openssl_get_cipher_methods()) ) {
Throw new Exception('Encryption method ' . $method . ' not supported.');
} else if( ! in_array(strtolower($hashfunc), hash_algos()) ) {
Throw new Exception('Hashing method ' . $hashfunc . ' not supported.');
}
$this->method = $method;
$this->hashfunc = $hashfunc;
$this->iv_size = openssl_cipher_iv_length($this->method);
}
public function encrypt($password, $data) {
$iv = $this->hashIV($password);
$infostr = sprintf('$%s$%s$', $this->method, $this->hashfunc);
return $infostr . openssl_encrypt($data, $this->method, $password, 0, $iv);
}
public function decrypt($password, $data) {
$data_arr = explode('$', $data);
if( ! count($data_arr) == 4 ) {
throw new Exception('Bad input data.');
}
// var_export($data_arr);
$iv = $this->hashIV($password);
// echo base64_encode($iv);
if( ! $res = openssl_decrypt($data, $this->method, $password, 0, $iv) ) {
throw new Exception(openssl_error_string());
} else { return $res; }
}
private function hashIV($password, $method=NULL) {
if( is_null($method) || ! in_array(strtolower($method), hash_algos())) {
$hashfunc = $this->hashfunc;
} else {
$hashfunc = $method;
}
$myhash = hash($hashfunc, $password, TRUE);
while( strlen($myhash) < $this->iv_size ) {
$myhash .= hash($hashfunc, $myhash, TRUE);
}
return substr($myhash, 0, $this->iv_size);
}
} // -- end class MyEncrypt -- //
$c = new MyEncrypt("AES-256-CBC", "SHA256");
$msg_enc = $c->encrypt('pass', 'blah blah this is my data!');
echo $msg_enc . "\n" . var_export($c->decrypt('pass', $msg_enc), true);
答案 0 :(得分:5)
MyEncrypt类中的加密函数返回一个'$'分隔的字符串,其中只有最后一部分是base64编码的加密数据。您只需传递该部分而不是前缀($ AES-256-CBC $ SHA512)。
因此,如果您将$ data_arr [3]传递给openssl_decrypt函数而不是$ data,那么事情就可以了。我尝试使用php解释器,下面是输出。
> php -f x.php
$AES-256-CBC$SHA256$kJ+DIShnFOs0cGsDiVnXXMdBj1GoLYywrhz+lv3W/dk=
'blah blah this is my data!'