![](/img/trans.png)
[英]AES/CBC/PKCS5Padding Java Encrypting Error - javax.crypto.BadPaddingException: Given final block not properly padded
[英]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模式 。
還是您在做完全不同的事情?
使用CipherInputStream
和CipherOutputStream
,流將處理對密碼的所有調用(這就是在初始化時將密碼傳遞給它的原因)。 您只需要正確地對其進行初始化,並通過流傳輸數據,密碼流將對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.