web-dev-qa-db-ja.com

openssl ivとは何ですか?なぜキーとivが必要なのですか?

次のスクリプトを使用して、一部のデータを暗号化および復号化しようとしています。現在の暗号化が新しいサーバーで機能しないため、これを使用しています。現在、mcryptを使用しているため、opensslに変更します。

データベースでは、128ビットキーを使用するAES暗号化を使用しているため、キーとは何かを知っていますが、openssl ivとは何ですか?そして、なぜ私は鍵とivが必要なのでしょうか。

使用しようとしているコードはこれです。これは、暗号化についてよく理解していないため、Webサイトで見つけました。

キーが別の場所に保持されるように、明らかに変更します。

function encrypt_decrypt($action, $string) {
    $output = false;

    $encrypt_method = "AES-256-CBC";
    $secret_key = 'This is my secret key';
    $secret_iv = 'This is my secret iv';

    // hash
    $key = hash('sha256', $secret_key);

    // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
    $iv = substr(hash('sha256', $secret_iv), 0, 16);

    if( $action == 'encrypt' ) {
        $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
        $output = base64_encode($output);
    }
    else if( $action == 'decrypt' ){
        $output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
    }

    return $output;
}

$plain_txt = "This is my plain text";
echo "Plain Text = $plain_txt\n";

$encrypted_txt = encrypt_decrypt('encrypt', $plain_txt);
echo "Encrypted Text = $encrypted_txt\n";

$decrypted_txt = encrypt_decrypt('decrypt', $encrypted_txt);
echo "Decrypted Text = $decrypted_txt\n";

if( $plain_txt === $decrypted_txt ) echo "SUCCESS";
else echo "FAILED";

echo "\n";
13
Thomas Williams

初期化ベクトルは、CBC(Cipher Block Chaining)モードのAESを機能させるものの一部です-IVはOpenSSLに固有のものではありません。 CBCは、前のブロックと現在のブロックのXOR演算を行います。最初のブロックには前のブロックがないため、IVがその目的を果たします。

これが必要な理由には、ブロック暗号がどのように機能するかについての少しの理解が必要です。この連鎖とIVがなければ、ECBまたは電子コードブックと呼ばれるAESモードが残ります。 ECBには、他の多くの問題の中でも、選択されたプレーンテキスト攻撃を可能にする弱点があります。

CBC初期化ベクトルのベストプラクティスに少し時間をかけることをお勧めします。それらを誤って使用すると、AESの全体的なセキュリティが低下する可能性があります。簡単な説明は次のとおりです。

  • IVはランダムであり、CSPRNGによって生成される必要があります。
  • IVは再利用しないでください。つまり、プレーンテキスト「A」とプレーンテキスト「B」を同じIVで暗号化しないでください。すべてのレコードには独自のIVが必要です。
  • IVは鍵のような秘密ではありません。暗号文とともに平文で保存できます。

また、このアドバイスはAES-CBCにのみ適用されることに注意してください。 GCMなど、AESの他のモードを調査する場合、これは適用されません。

16
vcsjones

「ハッシュ化されたキー」と「iv」を混同したのではないかと思います(神は暗号を開始したときに私がしたことを知っています)。ハッシュキーはまさにあなたがしたことです。 ivでは、同じキーで暗号化が行われるたびに異なるランダムデータを使用する必要があります。 (私の経歴:セッションデータを暗号化/復号化するpdoセキュアセッションハンドラーを構築する必要があったため、openssl拡張を使用してAES-256-CBCを実装することになりました)

誰かがここに来た場合のほんの小さなヒント。

// iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
$iv = substr(hash('sha256', $secret_iv), 0, 16);

ivはivを生成する正しい方法ではありません+ ivは取得するのと同じくらいランダムでなければならないため、secret_ivを必要としません。ハッシュと同じように扱わない(または理解しない)。

Openssl拡張機能にアクセスできるため、選択した暗号のivを生成するより良い/より安全な方法があります。opensslは暗号のivの適切な長さも通知できます。

$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('AES-256-CBC'));

バイナリ形式になるため、16進数で必要な場合はbin2hex($ iv)を使用します。生成されたivをmysqlに保存する必要がある場合、生の形式で保存します(フィールドタイプvarbinary、binaryも機能します)。

もう一つ。 openssl_encryptと_decryptの両方で0に設定された$ optionsタグがあります。つまり、「trueに設定すると生の出力データとして返され、それ以外の場合、戻り値はbase64エンコードされます」。

4
ConfusedAmish