web-dev-qa-db-ja.com

暗号:IllegalBlockSizeExceptionの理由は何ですか?

Cipher で作業したとき、次のことがわかりました。

暗号化コード:

Cipher aes = Cipher.getInstance("AES");
aes.init(Cipher.ENCRYPT_MODE, generateKey());
byte[] ciphertext = aes.doFinal(rawPassword.getBytes());

復号化コード:

Cipher aes = Cipher.getInstance("AES");
aes.init(Cipher.DECRYPT_MODE, generateKey());
byte[] ciphertext = aes.doFinal(rawPassword.getBytes());

復号化コードを実行すると、IllegalBlockSizeException(入力長は16の倍数である必要があります...)が発生します。

しかし、復号化コードをに変更すると

Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding"); //I am passing the padding too
aes.init(Cipher.DECRYPT_MODE, generateKey());
byte[] ciphertext = aes.doFinal(rawPassword.getBytes());

それはうまくいきます。 algorithm/mode/paddingのパターンであると理解しています。だから、パディングについては触れなかったからだと思いました。だから私は暗号化中にモードとパディングを与えてみました、

暗号化コード:

Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");//Gave padding during encryption too
aes.init(Cipher.ENCRYPT_MODE, generateKey());
byte[] ciphertext = aes.doFinal(rawPassword.getBytes());

復号化コード:

Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
aes.init(Cipher.DECRYPT_MODE, generateKey());
byte[] ciphertext = aes.doFinal(rawPassword.getBytes());

ただし、IllegalBlockSizeExceptionで失敗します。

理由、例外の理由、およびその下で正確に何が起こっているのか。誰かが助けることができれば?前もって感謝します

[〜#〜]更新[〜#〜]

問題は、暗号化および復号化する文字列にあるようです。なぜなら、私が言ったコードでさえ、常に機能するとは限らないからです。私は基本的にUUIDを暗号化しています(例:8e7307a2-ef01-4d7d-b854-e81ce152bbf6)。特定の文字列で機能し、特定の他の文字列では機能しません。

暗号化された文字列の長さは64で、16で割り切れます。はい、同じマシンで実行しています。

秘密鍵の生成方法:

    private Key generateKey() throws NoSuchAlgorithmException {
    MessageDigest digest = MessageDigest.getInstance("SHA");
            String passphrase = "blahbl blahbla blah";
    digest.update(passphrase.getBytes());
    return new SecretKeySpec(digest.digest(), 0, 16, "AES");
}
19
shazinltc

復号化中に、入力データがブロックサイズの倍数(AESの場合は16バイト)でない場合、のみIllegalBlockSizeExceptionを取得できます。

キーまたはデータが無効である(ただし長さが正しい)場合、平文ではPKCS#5のパディングが間違っているため、BadPaddingExceptionが返されます。非常にまれに、パディングが偶然に正しく表示され、例外はまったくありません。


N.B.常にパディングとモードを指定することをお勧めします。そうしないと、プロバイダーがデフォルトを変更した場合に驚かされる可能性があります。 AFAIK、Sunプロバイダーは"AES""AES/ECB/PKCS5Padding"に変換します。

9
Duncan Jones

私は内部を完全には理解していませんが、問題が何であるかを見つけました。

暗号化された文字列をGETリクエストパラメータとしてフェッチします。文字列に安全でない文字が含まれているため、リクエストを超えると文字列が破損します。解決策は、URLエンコードとデコードを行うことです。

RLEncoder および RLDecoder を使用して正常に実行できます。

これで結果は一貫しています。ありがとう:)

誰かがこれにもっと貢献できれば幸いです。

5
shazinltc