在命令行上无法解密openssl_encrypt()输出 [英] Cannot decrypt openssl_encrypt() output on command line

查看:915
本文介绍了在命令行上无法解密openssl_encrypt()输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经编写了一个使用openssl进行对称加密的小类,它在PHP内加密和解密,但我似乎无法使用命令行对输出进行解密,也可以以相同的方式加密相同的数据。 / p>

我的课程是:

  Class SimpleCrypt {

public static function encrypt($ password,$ data,$ enc_method ='AES-256-CBC',$ hash_method ='SHA512'){
self :: check_methods($ enc_method,$ hash_method);
$ iv = self :: hashIV($ password,$ hash_method,openssl_cipher_iv_length($ enc_method));
$ infostr = sprintf('$%s $%s $',$ enc_method,$ hash_method);
return $ infostr。 openssl_encrypt($ data,$ enc_method,$ password,false,$ iv);
}

public static function decrypt($ password,$ edata){
$ e_arr = explode('$',$ edata);
if(count($ e_arr)!= 4){
抛出新的异常(给定数据缺少关键部分);
}
$ enc_method = $ e_arr [1];
$ hash_method = $ e_arr [2];
self :: check_methods($ enc_method,$ hash_method);
$ iv = self :: hashIV($ password,$ hash_method,openssl_cipher_iv_length($ enc_method));
return openssl_decrypt($ e_arr [3],$ enc_method,$ password,false,$ iv);
}

私有静态函数hashIV($ password,$ method,$ iv_size){
$ myhash = hash($ method,$ password,TRUE);
while(strlen($ myhash)< $ iv_size){
$ myhash。= hash($ method,$ myhash,TRUE);
}
return substr($ myhash,0,$ iv_size);


私有静态函数check_methods($ enc,$ hash){
if(!function_exists('openssl_encrypt')){
抛出新的异常('openssl_encrypt () 不支持。');
} else if(!in_array($ enc,openssl_get_cipher_methods())){
引发新的异常('Encryption method'。$ enc。'不支持。
} else if(!in_array(strtolower($ hash),hash_algos())){
抛出新的异常('Hashing方法'$ hash。'不支持。
}
}

} // - 结束类SimpleCrypt - //


$ enc = SimpleCrypt :: encrypt( '通过','测试数据');
$ dec = SimpleCrypt :: decrypt('pass',$ enc);
echo $ enc。 \\\
。 $分解;
//输出:
// $ AES-256-CBC $ SHA512 $ yH0uN95Vya0pTwcoJRFb + g ==
//测试数据

这一段代码重现了IV:

  php -r'echo strtoupper(bin2hex(substr(hash(SHA512,pass,true),0,openssl_cipher_iv_length(AES-256-CBC)));'
/ / output:5B722B307FCE6C944905D132691D5E4A

但是这个代码给了我不像输入的乱码otuput: p>

  $ echo yH0uN95Vya0pTwcoJRFb + g == | base64 -d | openssl enc -AES-256-CBC -d -nosalt -nopad -k pass -iv 5B722B307FCE6C944905D132691D5E4A 
ã`ÈAgè}½5øÍÝEÞ
00000000 e3 60 c8 41 67 e8 7d bd 35 00 f8 cd dd 45 13 de | .`.Ag} 5 ....è..。。|

从命令行编码数据给我:

  $ echotest data| openssl enc-e -AES-256-CBC -nosalt -k pass -iv 5B722B307FCE6C944905D132691D5E4A | hexdump -C 
00000000 ca fc 84 6a 95 51 8f 0e 61 14 96 77 4e 22 dd 39 | ... jQ.a..wN.9 |

$ echotest数据| openssl enc -e -AES-256-CBC -nosalt -k pass -iv 5B722B307FCE6C944905D132691D5E4A | base64
yvyEapVRjw5hFJZ3TiLdOQ ==

任何人都可以告诉我我在PHP代码中做错了什么?



解决方案



只要从Daniel的答案中回顾一下解决方案,我们需要使用 -K 参数来打开openssl而不是 -k -pass ,它期望字符串的十六进制表示。例如:

  echo strtoupper(bin2hex('pass')); 
//输出:70617373

然后正确的命令是:

  echo yH0uN95Vya0pTwcoJRFb + g == | base64 -d | openssl enc -AES-256-CBC -d -nosalt -K 70617373 -iv 5B722B307FCE6C944905D132691D5E4A | hexdump -C 
00000000 74 65 73 74 20 64 61 74 61 | tes t数据|


解决方案

严重命名为密码 PHP的参数openssl_encrypt()不是密码,它是实际的键。当使用小写 -k 的命令行 openssl enc 时,OpenSSL将使用密钥从密码中导出密钥推导函数。您要使用大写 -K openssl enc 和键的十六进制表示;并确保在密码参数中的 openssl_encrypt()一个足够长的密钥。



另请参见中第一个用户提供的注释openssl_encrypt()上的PHP手册。


I've written a small class for symmetric encryption with openssl, and it encrypts and decrypts fine within PHP, but I cannot seem to either decrypt the output using the command line, or encrypt the same data in the same way.

My class is:

Class SimpleCrypt {

    public static function encrypt($password, $data, $enc_method='AES-256-CBC', $hash_method='SHA512') {
        self::check_methods($enc_method, $hash_method);
        $iv = self::hashIV($password, $hash_method, openssl_cipher_iv_length($enc_method));
        $infostr = sprintf('$%s$%s$', $enc_method, $hash_method);
        return $infostr . openssl_encrypt($data, $enc_method, $password, false, $iv);
    }

    public static function decrypt($password, $edata) {
        $e_arr = explode('$', $edata);
        if( count($e_arr) != 4 ) {
            Throw new Exception('Given data is missing crucial sections.');
        }
        $enc_method = $e_arr[1];
        $hash_method = $e_arr[2];
        self::check_methods($enc_method, $hash_method);
        $iv = self::hashIV($password, $hash_method, openssl_cipher_iv_length($enc_method));
        return openssl_decrypt($e_arr[3], $enc_method, $password, false, $iv);
    }

    private static function hashIV($password, $method, $iv_size) {
        $myhash = hash($method, $password, TRUE);
        while( strlen($myhash) < $iv_size ) {
            $myhash .= hash($method, $myhash, TRUE);
        }
        return substr($myhash, 0, $iv_size);
    }

    private static function check_methods($enc, $hash) {
        if( ! function_exists('openssl_encrypt') ) {
            Throw new Exception('openssl_encrypt() not supported.');
        } else if( ! in_array($enc, openssl_get_cipher_methods()) ) {
            Throw new Exception('Encryption method ' . $enc . ' not supported.');
        } else if( ! in_array(strtolower($hash), hash_algos()) ) {
            Throw new Exception('Hashing method ' . $hash . ' not supported.');
        }
    }

} // -- end class SimpleCrypt -- //


$enc = SimpleCrypt::encrypt('pass', 'test data');
$dec = SimpleCrypt::decrypt('pass', $enc);
echo $enc . "\n" . $dec;
// Output:
// $AES-256-CBC$SHA512$yH0uN95Vya0pTwcoJRFb+g==
// test data

This bit of code reproduces the IV:

php -r 'echo strtoupper(bin2hex(substr(hash("SHA512", "pass", true), 0, openssl_cipher_iv_length("AES-256-CBC"))));'
//output: 5B722B307FCE6C944905D132691D5E4A

But this code gives me garbled otuput that doesn't resemble the input:

$ echo yH0uN95Vya0pTwcoJRFb+g== | base64 -d | openssl enc -AES-256-CBC -d -nosalt -nopad -k pass -iv 5B722B307FCE6C944905D132691D5E4A
ã`ÈAgè}½5øÍÝEÞ
00000000  e3 60 c8 41 67 e8 7d bd  35 00 f8 cd dd 45 13 de  |.`.Ag.}.5....E..|

Encoding the data from the command line gives me:

$ echo "test data" | openssl enc -e -AES-256-CBC -nosalt -k pass -iv 5B722B307FCE6C944905D132691D5E4A | hexdump -C
00000000  ca fc 84 6a 95 51 8f 0e  61 14 96 77 4e 22 dd 39  |...j.Q..a..wN".9|

$ echo "test data" | openssl enc -e -AES-256-CBC -nosalt -k pass -iv 5B722B307FCE6C944905D132691D5E4A | base64
yvyEapVRjw5hFJZ3TiLdOQ==

Can anyone tell me what I've done incorrectly in my PHP code?

Solution

Just to recap the solution from the Daniel's answer, we need to use the -K argument to openssl rather than -k or -pass and it expects a hex representation of the string. eg:

echo strtoupper(bin2hex('pass'));
//output: 70617373

And then the proper command is:

echo yH0uN95Vya0pTwcoJRFb+g== | base64 -d | openssl enc -AES-256-CBC -d -nosalt -K 70617373 -iv 5B722B307FCE6C944905D132691D5E4A | hexdump -C
00000000  74 65 73 74 20 64 61 74  61                       |test data|

解决方案

The badly named password argument to PHP's openssl_encrypt() is not a password, it is the actual key. When using command line openssl enc with lower-case -k, OpenSSL will derive a key from the password using a key derivation function. You want to use openssl enc with upper-case -K and a hexadecimal representation of the key; and make sure to hand openssl_encrypt() a long enough key in the password argument.

See also the very first user-contributed note in the PHP manual on openssl_encrypt().

这篇关于在命令行上无法解密openssl_encrypt()输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆