java - 错误需要修复 - javax.crypto.BadPaddingException:给定最终块未正确填充
问题描述
我不确定我做错了什么。简而言之,我想使用给定的 secretKey 并使用 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 编码的字符串,所以我最终没有遇到编码问题。
我的课:
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;
}
}
}
还可以尝试使用与我的长度相同的密钥,先尝试一下,因为这可能是问题所在。在尝试对 while 循环的字符串操作使用 Base64 之后。
希望它可以帮助你。
推荐阅读
- python - 使用 pyodbc 检索 SQL Server 数据返回意外的数据值
- json - 逻辑应用程序:如何在 JSON 变量中添加根节点?
- python - AttributeError:模块“pygame.font”没有属性“Sysfont”,
- node.js - getParametersByPath 页面大小
- sql-server - 配置链接服务器时提供程序字符串是什么
- javascript - 根据键从对象创建一个值数组
- c++ - 多个类之间的C++循环依赖
- firebase - Flutter - Firebase - 按列表项值查询
- swift - 为什么我的 collectionview 单元格没有动画?
- javascript - 如何用图像和文本填充一个数组值?- HTML/Javascript