9

2 つのクライアントが安全なメッセージをやり取りしているとします。

このブロックはメッセージごとに毎回実行する必要がありますか、または開始時に 1 回だけ実行する必要があります。

cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
output = cipher.doFinal(content);

内部構造を (まだ) 完全には理解していませんが、セキュリティ上の理由から、各メッセージの IV を変更することが重要であることは理解しています。したがって、この質問への答えは、そのステップが内部で doFinal() ステージまたは init() のどちらで発生するかによって異なると思います...?

4

1 に答える 1

6

あなたは正しいです: 安全のために、メッセージごとに新しいランダムな IV を使用する必要があります。これは、暗号を再作成するか、後続のメッセージごとに IV を自分でランダムに設定する必要があることを意味します。暗号またはモードを変更した場合、ランダムに設定する必要がある他の状態が存在する可能性があり、暗号を再初期化することですべてを処理できるため、前者の方がおそらく安全です。

これを行わないと、SSL が IV再利用で持っていたのと同じかなり悪いバグが発生します。

Cipher.doFinal は、暗号をランダムな IV にリセットしません。実際には、それよりもはるかに悪いことに、内部状態が初期状態と同じ IV にリセットされているように見えます。このコードで示されているように。

    Cipher f = Cipher.getInstance("AES/CBC/PKCS5Padding");
     byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
                0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };

            SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
    f.init(Cipher.ENCRYPT_MODE, key);
    byte[] iv = f.getIV();
    System.out.println(Arrays.toString(f.doFinal("hello".getBytes())));
    System.out.println(Arrays.toString(f.getIV()));
    System.out.println(Arrays.toString(f.doFinal("hello".getBytes())));
    System.out.println(Arrays.toString(f.getIV()));
    System.out.println( Arrays.equals(f.getIV(), iv)); // true
于 2012-10-25T15:35:28.243 に答える