php - OpenSSL 错误 : EVP_DecryptFinal_ex:wrong final block length

标签 php encryption openssl

我要回顾一些我之前为加密而编写的代码 [包含在这篇文章的底部],但我遇到了一个错误,我找不到解决方法。每当我尝试解密我的数据时,我都会从 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);

最佳答案

MyEncrypt 类中的加密函数返回一个以“$”分隔的字符串,其中只有最后一部分是 base64 编码的加密数据。您只需要传递该部分而不是前缀($AES-256-CBC$SHA512)。

因此,如果您将 $data_arr[3] 而不是 $data 传递给 openssl_decrypt 函数,一切都会正常进行。我用 php 解释器试了一下,下面是输出。

> php -f x.php
$AES-256-CBC$SHA256$kJ+DIShnFOs0cGsDiVnXXMdBj1GoLYywrhz+lv3W/dk=
'blah blah this is my data!'

关于php - OpenSSL 错误 : EVP_DecryptFinal_ex:wrong final block length,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18878586/

相关文章:

php - 如何拆分表单 ["1","2","3"] 的数据并在数组中存储为 [1,2,3] in php

networking - 在 tcpdump 之类的工具中,网络数据包究竟是在什么时候捕获的?

ssl - 对于具有名称约束的证书,OpenSSL 验证意外失败,出现 "permitted subtree violation"

c++ - OpenSSL:服务器无法验证客户端证书

python - 安装 scrapy 出错

php - 如何按位比较字符串

php - 我如何从 OOP 编程中的类返回多个数据库记录

php - 使用html和php将图像上传到mysql

python - Django 加密 key 完整性

c++ - 维吉尼亚密码