2

ファイルからテキストを暗号化/復号化しようとしていますが、次のエラーが表示されます:

Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher

AES/ECB/PKCS5Padding で AES 128 ビットを使用しています。このエラーが発生する理由は何ですか? これが私のコードです:

public class AES_Encryption  {

public static void main(String[] args) throws Exception {
    String str = new Scanner(new File("src//plainText.txt")).useDelimiter("\\Z").next();
    FileWriter fstream = new FileWriter("src//cipherText.txt");
    BufferedWriter out = new BufferedWriter(fstream);
    FileWriter fstream2 = new FileWriter("src//decrpytedText.txt");
    BufferedWriter out2 = new BufferedWriter(fstream2);
    System.out.println("" + str);


    KeyGenerator keyGen = KeyGenerator.getInstance("AES");
    keyGen.init(128);
    Key key = keyGen.generateKey();
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, key);
    byte[] cipherText = cipher.doFinal(str.getBytes());
    String ct = new String(cipherText);
    System.out.println( new String(cipherText, "UTF8") );
    out.append(ct);
    out.close();


    String cipherT = new Scanner(new File("src//cipherText.txt")).useDelimiter("\\Z").next();
    cipher.init(Cipher.DECRYPT_MODE, key);

    //byte[] decVal = Base64.decode(cipherT.getBytes());
    byte[] newPlainText = cipher.doFinal(cipherT.getBytes());
    String dt = new String(newPlainText, "UTF8");
    out2.append(dt);
    out2.close();
}

}

4

2 に答える 2

3

あなたのエラーは、暗号文を文字列として扱っています:

String ct = new String(cipherText); // <--- Noooo!

バイト配列には、デフォルトの文字セットの文字として表現できない値があります。

ファイルの読み取りまたは書き込みを行う場合でも、常に暗号文をバイト配列として扱います。

于 2013-01-31T11:58:14.797 に答える
1

Cipher APIのドキュメントで説明されているように、次の場合にIllegalBlockSizeExceptionが発生します。

IllegalBlockSizeException-この暗号がブロック暗号である場合、パディングは要求されておらず(暗号化モードのみ)、この暗号によって処理されるデータの合計入力長はブロックサイズの倍数ではありません

あなたの場合、あなたは文字列を正しく暗号化していますが、復号化中に暗号文をとして扱い、次にバイト配列をのメソッドにString入れています。文字列のバイト配列変換は、バイナリモードでファイルからバイト配列を読み取ることと同じではありません。文字列APIドキュメントに記載されている機能と制限は次のとおりです。cipherT.getBytes()doFinalCipherString.toBytes()

プラットフォームのデフォルトの文字セットを使用して、この文字列を一連のバイトにエンコードし、結果を新しいバイト配列に格納します。この文字列をデフォルトの文字セットでエンコードできない場合のこのメソッドの動作は指定されていません。CharsetEncoderクラスは、エンコードプロセスをさらに制御する必要がある場合に使用する必要があります。

私があなたに提案するのはcipherText.txt File 、バイナリモードで読み取り、ファイルを読み取った後に取得したバイト配列をのdoFinalメソッドに配置することですCipher。次のようにコードを変更しました。

public class AES_Encryption  {
public static void main(String[] args) throws Exception {
    String str = new Scanner(new File("plainText.txt")).useDelimiter("\\t").next();
    FileOutputStream fstream = new FileOutputStream("cipherText.txt");
    BufferedOutputStream out = new BufferedOutputStream(fstream);
    FileOutputStream fstream2 = new FileOutputStream("decrpytedText.txt");
    BufferedOutputStream out2 = new BufferedOutputStream(fstream2);
    System.out.println("INPUT String:\n" + str);


    KeyGenerator keyGen = KeyGenerator.getInstance("AES");
    keyGen.init(128);
    Key key = keyGen.generateKey();
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, key);
    byte[] cipherText = cipher.doFinal(str.getBytes());
    System.out.println("ENCRYPTED String:\n"+new String(cipherText, "UTF8") );
    out.write(cipherText);
    out.flush();
    out.close();


    //String cipherT = new Scanner(new File("cipherText.txt")).nextLine();
    BufferedInputStream bfin = new BufferedInputStream(new FileInputStream(new File("cipherText.txt")));//To read the file in Binary Mode.
    cipher.init(Cipher.DECRYPT_MODE, key);
    int BUFFERSIZE = 1024;
    byte[] readBytes = new byte[BUFFERSIZE];
    byte[] data = null;
    int totalRead = -1;
    while( (totalRead = bfin.read(readBytes))!=-1)
    {
        byte[] temp = new byte[(data == null ? totalRead : data.length)];
        System.arraycopy((data==null ? readBytes : data),0,temp,0, temp.length); 
        data = new byte[(data == null ? 0 : data.length) + totalRead];
        System.arraycopy(temp, 0, data, 0, temp.length);
        System.arraycopy(readBytes, 0, data, data.length - temp.length, totalRead);
    }
    if (data!=null)
    {
        byte[] newPlainText = cipher.doFinal(data);
        out2.write(newPlainText);
        out2.flush();
        System.out.println("DECRYPTED String:\n"+new String(newPlainText,"UTF8"));
    }
    else
    {
        System.out.println("No Data Found");
    }
    //String dt = new String(newPlainText, "UTF8");
    out2.close();
}
}

これが、発生した例外の解決に役立つことを願っています...

于 2013-01-31T17:24:52.807 に答える