1

私はopensslを使用して対称暗号化用の小さなクラスを作成しました。これは、PHP内で正常に暗号化および復号化されますが、コマンドラインを使用して出力を復号化することも、同じデータを同じ方法で暗号化することもできないようです。

私のクラスは:

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

このコードはIVを再現します。

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

しかし、このコードは、入力に似ていない文字化けしたotuputを私に与えます:

$ 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..|

コマンドラインからデータをエンコードすると、次のようになります。

$ 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==

PHPコードで間違ったことを誰かに教えてもらえますか?

解決

ダニエルの答えから解決策を要約するために、or-Kではなくopensslの引数を使用する必要があり、文字列の16進表現が必要です。例えば:-k-pass

echo strtoupper(bin2hex('pass'));
//output: 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                       |test data|
4

1 に答える 1

1

PHPに対する誤った名前passwordの引数openssl_encrypt()はパスワードではなく、実際のキーです。openssl enc小文字のコマンドラインを使用する場合-k、OpenSSLは鍵導出関数を使用してパスワードから鍵を導出します。キーのopenssl enc大文字と16進表現で使用したい。引数に十分な長さのキー-Kを渡すようにしてください。openssl_encrypt()password

openssl_encrypt()に関するPHPマニュアルの最初のユーザー投稿メモも参照してください。

于 2013-02-23T20:12:12.520 に答える