解密文本时出现IllegalBlockSizeException

时间:2015-07-28 02:54:13

标签: java exception encryption

当我尝试解密Java程序中的文本时出现此错误:

The program was unable to decrypt the file because of the following reason:
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when
decrypting with padded cipher
        at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:913)
        at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
        at com.sun.crypto.provider.DESCipher.engineDoFinal(DESCipher.java:314)
        at javax.crypto.Cipher.doFinal(Cipher.java:2165)
        at encrypt.decrypt(encrypt.java:121)
        at encrypt.main(encrypt.java:156)

我的完整代码为here

简化代码:

import java.io.*;
import java.util.*;
import java.nio.file.*;
import java.nio.charset.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;

public class encrypt {
    public static void encrypt() {
        try {
            String path = null;
            String fileName;
            KeyGenerator keyGenerator;
            SecretKey secretKey = null;
            Cipher DESCipher = null;
            byte[] data;
            String encryptedData;
            File file = null, dataFile = null, keyFile = null;
            Scanner scanner;
            BufferedWriter bufferedWriter;

            path = Paths.get("").toAbsolutePath().toString();
            keyGenerator = KeyGenerator.getInstance("DES");
            secretKey = keyGenerator.generateKey();
            DESCipher = Cipher.getInstance("DES");

            if(null == secretKey || null == DESCipher) {
                System.exit(1);
            }

            scanner = new Scanner(System.in);

            System.out.print("File to encrypt: ");
            fileName = scanner.nextLine();
            file = new File(fileName);

            while(!(file.exists() && !file.isDirectory())) {
                System.out.println("Error. File was not found.\n");
                System.out.print("File to encrypt: ");

                fileName = scanner.nextLine();
                file = new File(fileName);
            }

            data = Files.readAllBytes(Paths.get(fileName));

            DESCipher.init(Cipher.ENCRYPT_MODE, secretKey);
            encryptedData = new String(DESCipher.doFinal(data));
            encryptedData = Base64.getEncoder().encodeToString(
                encryptedData.getBytes(Charset.forName("UTF-8")));

            dataFile = new File(path + "/" + fileName + ".data");
            keyFile = new File(path + "/" + fileName + ".key");

            /* Write content to file */
        } catch (Exception e) {
            /* Throw error */
            System.exit(1);
        }
    }

    public static void decrypt() {
        try {
            String path = null;
            String dataFileName, keyFileName;
            Scanner scanner = null;
            Cipher DESCipher;
            SecretKey secretKey;
            File file = null;
            byte[] decodedKey, decryptedBytes;
            BufferedWriter bufferedWriter;

            path = Paths.get("").toAbsolutePath().toString();
            scanner = new Scanner(System.in);

            System.out.print("File to decrypt: ");
            dataFileName = scanner.nextLine();
            file = new File(dataFileName);

            while(!(file.exists() && !file.isDirectory())) {
                System.out.println("Error. File was not found.\n");
                System.out.print("File to decrypt: ");

                dataFileName = scanner.nextLine();
                file = new File(dataFileName);
            }

            System.out.print("Key file for decrypt: ");
            keyFileName = scanner.nextLine();
            file = new File(keyFileName);

            while(!(file.exists() && !file.isDirectory())) {
                System.out.println("Error. File was not found.\n");
                System.out.print("Key file for decrypt: ");

                keyFileName = scanner.nextLine();
                file = new File(keyFileName);
            }

            decodedKey = Base64.getDecoder().decode(
                new String(Files.readAllBytes(
                    Paths.get(keyFileName))));

            secretKey = new SecretKeySpec(
                decodedKey, 0, decodedKey.length, "DES");

            DESCipher = Cipher.getInstance("DES");
            DESCipher.init(Cipher.DECRYPT_MODE, secretKey);

            decryptedBytes = DESCipher.doFinal(
                Base64.getDecoder().decode(
                    new String(Files.readAllBytes(
                        Paths.get(dataFileName)))));

            /* Write content to file */
        } catch (Exception e) {
            /* Throw error */
            System.exit(1);
        }
    }

    public static void main(String[] args) {
        // Encrypt or decrypt?
    }
}

我试图检查从文件中读取的解码文本的长度,看起来长度实际上不是8的倍数。

我该怎么做才能解决此异常?我是否需要处理字符串以使其为8的倍数,或者我还能做什么?

1 个答案:

答案 0 :(得分:0)

您的问题与此question非常相关。你的代码:

        encryptedData = new String(DESCipher.doFinal(data));
        encryptedData = Base64.getEncoder().encodeToString(
            encryptedData.getBytes(Charset.forName("UTF-8")));

破坏加密的二进制数据。如果您正在写入文件,只需将二进制文件直接写入文件:

        FileOutputStream fos = new FileOutputStream(dataFile);
        fos.write(data);
        fos.flush();
        fos.close();

您的代码运行完全正常。如果您以后决定需要Base64,请直接使用它:

    encryptedData = Base64.getEncoder().encodeToString(data);
但是,我不会评论使用DES。