java - 需要修复错误 - javax.crypto.BadPaddingException : Given final block not properly padded

标签 java encryption aes cbc-mode file-encodings

我不知道我做错了什么。简而言之,我想使用给定的 key 并使用 iv 来解密文件,我使用以下代码来执行此操作:

package com.Crypt.test;

import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.SecureRandom;

public class AES256CBCTest {
    static String encoding = "UTF-8";
    public static void main(String[] args) throws Exception {
        String key = "BURP6070";
        File inputFile = new File("/Users/jaynigam/Documents/workspace/EncryptDecrypt/files/test.xml.enc");
    try {
        BufferedReader br = new BufferedReader(new FileReader(inputFile));
        String st;
        File outputFile =null;
        FileOutputStream outputStream = null;
        try {
            while ((st = br.readLine()) != null){
                //decrypt(someString.getBytes(encoding), key);
                 String decrypted = decrypt(st.getBytes(), key);
                 outputFile = new File("/Users/jaynigam/Documents/workspace/EncryptDecrypt/files/decryptTest.xml.dec");
                 outputStream = new FileOutputStream(outputFile);
                    byte[] strToBytes = decrypted.getBytes(encoding);
                    outputStream.write(strToBytes);

            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally {
            outputStream.close();
            br.close();
        }

    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
    //byte[] encrypted = encrypt(clean, key);



public static byte[] encrypt(String plainText, String key) throws Exception {
    byte[] clean = plainText.getBytes();

    // Generating IV.
    int ivSize = 16;
    byte[] iv = new byte[ivSize];
    SecureRandom random = new SecureRandom();
    random.nextBytes(iv);
    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

    // Hashing key.
    MessageDigest digest = MessageDigest.getInstance("SHA-1");
    digest.update(key.getBytes());
    byte[] keyBytes = new byte[32];
    System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);
    SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");

    // Encrypt.
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
    byte[] encrypted = cipher.doFinal(clean);

    // Combine IV and encrypted part.
    byte[] encryptedIVAndText = new byte[ivSize + encrypted.length];
    System.arraycopy(iv, 0, encryptedIVAndText, 0, ivSize);
    System.arraycopy(encrypted, 0, encryptedIVAndText, ivSize, encrypted.length);

    return encryptedIVAndText;
}

public static String decrypt(byte[] encryptedIvTextBytes, String key) throws Exception {
    int ivSize = 16;
    int keySize = 16;

    // Extract IV.
    byte[] iv = new byte[ivSize];
    System.arraycopy(encryptedIvTextBytes, 0, iv, 0, iv.length);
    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

    // Extract encrypted part.
    int encryptedSize = encryptedIvTextBytes.length - ivSize;
    byte[] encryptedBytes = new byte[encryptedSize];
    System.arraycopy(encryptedIvTextBytes, ivSize, encryptedBytes, 0, encryptedSize);

    // Hash key.
    byte[] keyBytes = new byte[keySize];
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    md.update(key.getBytes());
    System.arraycopy(md.digest(), 0, keyBytes, 0, keyBytes.length);
    SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");

    // Decrypt.
    Cipher cipherDecrypt = Cipher.getInstance("AES/CBC/NoPadding");
    cipherDecrypt.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
    byte[] decrypted = cipherDecrypt.doFinal(encryptedBytes);

    return new String(decrypted);
}
}

这会返回类似?lm:@?带?w?)P@?\?s????Ka???0??{???w|k??? 的输出o?\?。我已经尝试过UTF-8解码。但到现在为止仍然没有运气。有人对此有任何线索吗?

最佳答案

我遇到了和你完全相同的问题,并且也使用了相同的源代码! 我在使用返回和输入参数作为 byte[] 时遇到了问题,因此我将其转换为具有 Base64 编码的字符串,因此我最终没有遇到编码问题。

我的类(class):

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Base64;


public class PasswordManager {

    private static final Logger LOGGER = LoggerFactory.getLogger(PasswordManager.class);
    private static final String key = "DdFfGg998012jffW"; // 128 bit key

    private PasswordManager() {
    }

    public static String encrypt(String plainText) {
        if (plainText == null) {
            return null;
        }

        byte[] clean = plainText.getBytes();

        // Generating IV.
        int ivSize = 16;
        byte[] iv = new byte[ivSize];
        SecureRandom random = new SecureRandom();
        random.nextBytes(iv);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

        try {
            // Hashing key.
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            digest.update(key.getBytes(StandardCharsets.UTF_8));
            byte[] keyBytes = new byte[16];
            System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);
            SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");

            // Encrypt.
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
            byte[] encrypted = cipher.doFinal(clean);

            // Combine IV and encrypted part.
            byte[] encryptedIVAndText = new byte[ivSize + encrypted.length];
            System.arraycopy(iv, 0, encryptedIVAndText, 0, ivSize);
            System.arraycopy(encrypted, 0, encryptedIVAndText, ivSize, encrypted.length);

            return Base64.getEncoder().encodeToString(encryptedIVAndText);
        } catch (Exception e) {
            LOGGER.error("Exception in decrypting a password. Returning null", e);
            return null;
        }
    }

    public static String decrypt(String encryptedString) {
        if (encryptedString == null) {
            return null;
        }

        byte[] encryptedIvTextBytes = Base64.getDecoder().decode(encryptedString);
        int ivSize = 16;
        int keySize = 16;

        // Extract IV.
        byte[] iv = new byte[ivSize];
        System.arraycopy(encryptedIvTextBytes, 0, iv, 0, iv.length);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

        // Extract encrypted part.
        int encryptedSize = encryptedIvTextBytes.length - ivSize;
        byte[] encryptedBytes = new byte[encryptedSize];
        System.arraycopy(encryptedIvTextBytes, ivSize, encryptedBytes, 0, encryptedSize);
        try {
            // Hash key.
            byte[] keyBytes = new byte[keySize];
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(key.getBytes());
            System.arraycopy(md.digest(), 0, keyBytes, 0, keyBytes.length);
            SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");

            // Decrypt.
            Cipher cipherDecrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipherDecrypt.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
            byte[] decrypted = cipherDecrypt.doFinal(encryptedBytes);

            return new String(decrypted);
        } catch (Exception e) {
            LOGGER.error("Exception in decrypting a password. Returning null", e);
            return null;
        }

    }

}

还尝试使用与我的长度相同的 key ,首先尝试,因为这可能是问题所在。尝试在 while 循环中对字符串操作使用 Base64 后。

希望对您有帮助。

关于java - 需要修复错误 - javax.crypto.BadPaddingException : Given final block not properly padded,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51693054/

相关文章:

java - 如何在绘画中使用graphics2D或者有更好的方法来做到这一点?

java - 在 JTable 中保持单列静态

java - Spring Boot多个外部数据源存储在内部数据库中

java - Java和Android之间的加密/解密

c++ - 在 C++ 中实现 AES-128 混合列函数

java - Hibernate,无法从关系中获取数据

node.js - NodeJS 服务器文本哈希的安全性

encryption - 仅在登录时使用 ssl?或整个网站?

c - Vigenere 密码陷入无限循环

java - Java 中的传统加密和 PHP 中的解密