簡體   English   中英

解密AES / CBC / PKCS5Padding錯誤:鑒於未正確填充最終塊

[英]Decrypting of AES/CBC/PKCS5Padding Error: Given final block not properly padded

在解密大型加密文件上的AES / CBC / PKCS5Padding密碼時,我遇到“ 給定的最終塊未正確填充”錯誤。

我認為此問題是由於在cipher.init()方法中添加了錯誤的初始化向量引起的。

我在運行時無法讀取整個文件,因此需要加密固定大小的塊。 至此,我正在創建IV並將其存儲到.txt文件中。 但是在解密方法中,每個解密周期我都使用相同的IV。 我應該如何改變呢?

加密:

void encrypt() throws Exception{
    char[] password = passwordText.getText().toCharArray();
    byte[] salt = new byte[8];

    /* Creating and saving salt */
    salt = saveSalt(salt);

    /* Securing password */
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
    KeySpec spec = new PBEKeySpec(password, salt, 65536, 128);
    SecretKey tmp = factory.generateSecret(spec);
    SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

    if (choosedFile != null) {
        /* Choosing algorithm for decryption */
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

        /* Getting plain file */
        CipherInputStream fis = new CipherInputStream(new  FileInputStream(choosedFile), cipher);
        CipherOutputStream fos = new CipherOutputStream(new FileOutputStream(choosedFile+".encrypted"), cipher);

        /* Encrypting and Measuring */
        long startTime = System.currentTimeMillis();
        cipher.init(Cipher.ENCRYPT_MODE, secret);
        byte[] rawText = new byte[128];
        int count;
        while((count = fis.read(rawText)) > 0) {
            System.out.println(count);
            byte[] encryptedText = cipher.doFinal(rawText);
            fos.write(encryptedText, 0, count);
        }
        long stopTime = System.currentTimeMillis();

        fis.close();
        fos.close();

        /* Creating initialization vector and storing*/
        byte[] iVector = cipher.getIV();
        saveIVector(iVector);

        text.setText(text.getText() + "File was encrypted in " + (stopTime - startTime) + "ms.\n");
    }

}

解密:

    void decrypt() throws Exception {
    /* Getting salt */
    byte[] salt = getSalt();
    /* Getting initialization vector */
    byte[] iVector = getIVector();
    /* Getting user password */
    char[] password = passwordText.getText().toCharArray();


    /* Securing password */
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
    KeySpec spec = new PBEKeySpec(password, salt, 65536, 128);
    SecretKey tmp = factory.generateSecret(spec);
    SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

    if (choosedFile != null) {

        /* Choosing algorithm for decryption */
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        /* Getting ciphered file */


        CipherInputStream fis = new CipherInputStream(new  FileInputStream(choosedFile), cipher);
        CipherOutputStream fos = new CipherOutputStream(new FileOutputStream(choosedFile+".decrypted"), cipher);

        /* Decrypting and Measuring */
        long startTime = System.currentTimeMillis();
        cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iVector));
        byte[] rawText = new byte[128];
        int count;
        while((count = fis.read(rawText)) > 0) {
                byte[] encryptedText = cipher.doFinal(rawText);
                fos.write(encryptedText, 0, count);
            }

        long stopTime = System.currentTimeMillis();

        fis.close();
        fos.close();

擔心“直到我不得不將大文件切成固定大小的塊”。

使用“塊”代替上面的“塊”,因為“塊”在諸如AES之類的塊密碼中具有特定含義。

玩具將這些塊連接起來會做什么?

在CBC模式下,在第一個塊之后,先前的加密塊值將有效地用作下一個塊的IV。 因此,在分割然后連接塊時,上一個塊的最后一個塊的值就是下一個塊的IV。

請參閱CBC模式

還是您在做完全不同的事情?

使用CipherInputStreamCipherOutputStream ,流將處理對密碼的所有調用(這就是在初始化時將密碼傳遞給它的原因)。 您只需要正確地對其進行初始化,並通過流傳輸數據,密碼流將對update()doFinal()進行所需的調用。 請記住關閉蒸汽以觸發doFinal()

當前,您的代碼以一種不受控制的方式多次將數據傳遞通過密碼,從而使數據混亂。

另外,您僅需要一個CipherInputStream進行解密,以及一個CipherOutputStream進行加密。 在您當前的代碼中,您可以同時使用加密和解密。

加密可能是這樣的(這不處理iv ..):

...     
cipher.init(Cipher.ENCRYPT_MODE, secret);
InputStream is = new FileInputStream(choosedFile);
OutputStream os = new CipherOutputStream(new FileOutputStream(choosedFile+".encrypted"), cipher);

byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
    os.write(buffer, 0, len);
}

is.close();
os.close();
...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM