用错误的密码解密,最后的块没有正确填充
Decrypting with the wrong password, final block not properly padded
我有以下代码来定义密码class
import java.util.*;
import javax.crypto.Cipher;
import java.security.SecureRandom;
import java.security.NoSuchAlgorithmException;
import java.security.AlgorithmParameters;
import javax.crypto.*;
import javax.crypto.SecretKeyFactory;
import javax.crypto.SecretKey;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
public class Cipher{
private SecureRandom rand;
private SecretKeyFactory kFact;
private Cipher AESCipher;
private SecretKey key;
public Cipher(char[] mpw, byte[] salt){
try{
kFact = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
rand = SecureRandom.getInstance("SHA1PRNG");
AESCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
PBEKeySpec spec = new PBEKeySpec(mpw, salt, 1024, 256);
key = new SecretKeySpec(kFact.generateSecret(spec).getEncoded(),"AES");
}catch(Exception e){
System.out.println("no such algorithm");
}
}
/*Henc[k,m] will return c such that Hdec[k,HEnc[k,m]] = m
*/
public ArrayList<byte[]> HEnc(byte[] message) throws Exception{
ArrayList<byte[]> res = new ArrayList<byte[]>(2);
AESCipher.init(Cipher.ENCRYPT_MODE ,key);
AlgorithmParameters params = AESCipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] ctxt = AESCipher.doFinal(message);
res.add(0,iv);
res.add(1,ctxt);
return res;
}
public byte[] HDec(byte[] iv, byte[] cipher) throws Exception{
AESCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv) );
System.out.println("decrypting");
return AESCipher.doFinal(cipher);
}
/*public abstract byte[] HDec(SecretKey k, byte[] cipher);
*/
我对用不正确的密码解密密文很感兴趣,为此我定义了以下测试 class,
import java.util.*;
import java.io.*;
public class testCipher{
public static void main(String[] args) throws Exception{
while(true){
Scanner sc = new Scanner(System.in);
System.out.println("Enter master password");
String pass = sc.nextLine();
System.out.println("Enter incorrect password");
String fakepass = sc.nextLine();
System.out.println("Enter message to encrypt");
String message = sc.next();
String salt = "123";
HCipher goodEnc = new HCipher(pass.toCharArray(),salt.getBytes());
HCipher badEnc = new HCipher(fakepass.toCharArray(),salt.getBytes());
byte[] toEncrypt = message.getBytes();
ArrayList<byte[]> cipher = goodEnc.HEnc(toEncrypt);
byte[] ciphertxt = cipher.get(1);
byte[] iv = cipher.get(0);
while(true){
System.out.println("Enter 1 to decrypt with correct pass, 2 to decrypt with incorrect pass and 0 to end simulation");
int i = sc.nextInt();
if(i == 1){
System.out.println("Decrypting with correct password");
byte[] plaintxt = goodEnc.HDec(iv, ciphertxt);
System.out.println(new String(plaintxt));
}
if(i == 2){
System.out.println("Decrypting with incorrect password");
byte[] plaintxt = badEnc.HDec(iv, ciphertxt);
System.out.println(new String(plaintxt));
}
if(i == 0){
break;
}
}
}
}
}
使用正确的密码进行加密和解密效果很好。但是,当我尝试使用不正确的密码解密时,出现以下错误:
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:420)
at javax.crypto.Cipher.doFinal(Cipher.java:1966)
at HCipher.HDec(HCipher.java:54)
at testCipher.main(testCipher.java:52)
我猜这与我的 IV 有关,但我不确定如何修复它。有人有什么建议吗?
AES 是一种分组密码,以 16 字节为单位进行加密。填充用于在加密之前填充最后一个块,因此它适合偶数个块。
您正在指定 PKCS5Padding:
AESCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
填充的创建方式使其可以在解密过程中被识别和删除。如果您使用错误的密钥解密,Cipher 将无法识别有效的 pad,从而给您 BadPaddingException
如果您在没有填充的情况下实例化您的解密 Cipher
(因此您自己承担了该责任),您可以避免此异常。
我有以下代码来定义密码class
import java.util.*;
import javax.crypto.Cipher;
import java.security.SecureRandom;
import java.security.NoSuchAlgorithmException;
import java.security.AlgorithmParameters;
import javax.crypto.*;
import javax.crypto.SecretKeyFactory;
import javax.crypto.SecretKey;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
public class Cipher{
private SecureRandom rand;
private SecretKeyFactory kFact;
private Cipher AESCipher;
private SecretKey key;
public Cipher(char[] mpw, byte[] salt){
try{
kFact = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
rand = SecureRandom.getInstance("SHA1PRNG");
AESCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
PBEKeySpec spec = new PBEKeySpec(mpw, salt, 1024, 256);
key = new SecretKeySpec(kFact.generateSecret(spec).getEncoded(),"AES");
}catch(Exception e){
System.out.println("no such algorithm");
}
}
/*Henc[k,m] will return c such that Hdec[k,HEnc[k,m]] = m
*/
public ArrayList<byte[]> HEnc(byte[] message) throws Exception{
ArrayList<byte[]> res = new ArrayList<byte[]>(2);
AESCipher.init(Cipher.ENCRYPT_MODE ,key);
AlgorithmParameters params = AESCipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] ctxt = AESCipher.doFinal(message);
res.add(0,iv);
res.add(1,ctxt);
return res;
}
public byte[] HDec(byte[] iv, byte[] cipher) throws Exception{
AESCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv) );
System.out.println("decrypting");
return AESCipher.doFinal(cipher);
}
/*public abstract byte[] HDec(SecretKey k, byte[] cipher);
*/
我对用不正确的密码解密密文很感兴趣,为此我定义了以下测试 class,
import java.util.*;
import java.io.*;
public class testCipher{
public static void main(String[] args) throws Exception{
while(true){
Scanner sc = new Scanner(System.in);
System.out.println("Enter master password");
String pass = sc.nextLine();
System.out.println("Enter incorrect password");
String fakepass = sc.nextLine();
System.out.println("Enter message to encrypt");
String message = sc.next();
String salt = "123";
HCipher goodEnc = new HCipher(pass.toCharArray(),salt.getBytes());
HCipher badEnc = new HCipher(fakepass.toCharArray(),salt.getBytes());
byte[] toEncrypt = message.getBytes();
ArrayList<byte[]> cipher = goodEnc.HEnc(toEncrypt);
byte[] ciphertxt = cipher.get(1);
byte[] iv = cipher.get(0);
while(true){
System.out.println("Enter 1 to decrypt with correct pass, 2 to decrypt with incorrect pass and 0 to end simulation");
int i = sc.nextInt();
if(i == 1){
System.out.println("Decrypting with correct password");
byte[] plaintxt = goodEnc.HDec(iv, ciphertxt);
System.out.println(new String(plaintxt));
}
if(i == 2){
System.out.println("Decrypting with incorrect password");
byte[] plaintxt = badEnc.HDec(iv, ciphertxt);
System.out.println(new String(plaintxt));
}
if(i == 0){
break;
}
}
}
}
}
使用正确的密码进行加密和解密效果很好。但是,当我尝试使用不正确的密码解密时,出现以下错误:
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:420)
at javax.crypto.Cipher.doFinal(Cipher.java:1966)
at HCipher.HDec(HCipher.java:54)
at testCipher.main(testCipher.java:52)
我猜这与我的 IV 有关,但我不确定如何修复它。有人有什么建议吗?
AES 是一种分组密码,以 16 字节为单位进行加密。填充用于在加密之前填充最后一个块,因此它适合偶数个块。
您正在指定 PKCS5Padding:
AESCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
填充的创建方式使其可以在解密过程中被识别和删除。如果您使用错误的密钥解密,Cipher 将无法识别有效的 pad,从而给您 BadPaddingException
如果您在没有填充的情况下实例化您的解密 Cipher
(因此您自己承担了该责任),您可以避免此异常。