填充异常:给定的最后一个块没有正确填充



我正在尝试使用AES加密和解密我的文件,我的所有密码都存储在该文件中。

该算法在加密部分运行良好。但在解密时,它抛出错误

Message:Given final block not properly padded
javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
at javax.crypto.Cipher.doFinal(Cipher.java:2121)
at SearchDoc.dec_file(SearchDoc.java:327)
at SearchDoc.access$100(SearchDoc.java:52)
at SearchDoc$2$1.actionPerformed(SearchDoc.java:227)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$400(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

这里有什么问题?

代码:

//Starting decryption
try{
byte[] key = c_key.getBytes("ISO-8859-1");
key = Arrays.copyOf(key, 16); // use only first 128 bit
//System.out.println(Arrays.toString(key));
SecretKeySpec SecKey = new SecretKeySpec(key, "AES");
Cipher AesCipher = Cipher.getInstance("AES");
AesCipher.init(Cipher.DECRYPT_MODE, SecKey);
BufferedReader breader = new BufferedReader(new FileReader("download/enc_"+file));
String line;
boolean bool = false;
File f = new File(file);
bool = f.createNewFile();
if(bool==false){
f.delete();
bool = f.createNewFile();
}
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file, true)));
while ((line = breader.readLine()) != null){
byte[] cipher=null;
byte[] plain=null;
cipher=line.getBytes("ISO-8859-1");
plain=AesCipher.doFinal(cipher);
out.println(new String(plain,"ISO-8859-1"));
}
out.close();
return 1;
}
catch(Exception dcf){
System.out.println("Message:"+dcf.getMessage());
dcf.printStackTrace();
return 0;
}

新的AES代码:

import java.security.*;
import javax.crypto.spec.SecretKeySpec;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.*;
import sun.misc.*;
public class AESencrp {
private static final String ALGO = "AES";
private static final byte[] keyValue = 
new byte[] { 'T', 'h', 'e', 'B', 'e', 's', 't',
'S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' };
public static String encrypt(String Data) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encVal = c.doFinal(Data.getBytes());
String encryptedValue = new BASE64Encoder().encode(encVal);
return encryptedValue;
}
public static String decrypt(String encryptedData) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
private static Key generateKey() throws Exception {
Key key = new SecretKeySpec(keyValue, ALGO);
return key;
}
}

仅使用AES作为密码实例不会声明如何填充最终块。这就是加密和解密可能不同的原因。

请使用以下具体的加密实例之一(取决于您的加密模式):

AES/CCB/NoPackding
AES/CBC/PKCS5Padding
AES/EBC/NoPacking
AES/EBC/PKCS5 Padding

您可以在这里找到支持的密码列表

假设您加密了原始明文lineise,您将无法解密它lineise。密文可以包含任何字节值,包括n的值。因此,如果您在单独的调用中加密了每一行明文,有时您会得到一个密文"行",它有一个对应于n的字节。当您现在想要解密它时,这是不可能的,因为这些密码调用之间的边界是不同的。

要解决此问题,您需要在一次调用中加密整个文档(如果您有内存问题,请使用CipherInputStream/CipherOutputStream),或者单独加密每一行,但要确保您知道密文中的边界。

例如,后一种方法可以通过以不存在n的方式对每个部分密文进行编码来实现。例如,您可以将其编码为Base64,但这会使密文膨胀约33%。

我建议您使用前一种方法进行一次调用。


如flo所述,最好使用完全限定的密码字符串,因为不同的Java版本可能会使用不同的默认操作模式或填充,最终可能会出现不可恢复的密文。

相关内容

  • 没有找到相关文章

最新更新