使用 AES 算法解密的 BadPaddingException java
BadPaddingException with decryption using AES algorithm java
我正在尝试对视频和 pdf 进行加密。在我得到每个文件的流后,我分成缓冲区,然后我加密每个缓冲区并将所有缓冲区组合成一个加密文件。
对于加密,一切正常,但是当我尝试以相同的方式解密文件时,我在 doFinal 处遇到错误,即
{BadPaddingException : pad block corrupted
BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:739)}
这是我正在测试的代码
加密
public static byte[] encodeFile(byte[] key, byte[] fileData) throws Exception
{
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(fileData);
return encrypted;
}
解密
public static byte[] decodeFile(byte[] key, byte[] fileData)
{
byte[] decrypted=new byte[0];
try {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
decrypted= cipher.doFinal(fileData);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
return decrypted;
}
生成密钥
public static byte[] generateKey(String password) throws Exception
{
byte[] keyStart = password.getBytes("UTF-8");
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
sr.setSeed(keyStart);
kgen.init(256, sr);
SecretKey skey = kgen.generateKey();
return skey.getEncoded();
}
这是我解密文件的方法
public void decryptStream(String filePath) {
String outPath = Environment.getExternalStorageDirectory().toString() + "/" + fileName + "de" + "." + fileExtention;
filePath += "_secured." + fileExtention;
byte[] data = new byte[1024];
byte[] decryptData;
File file = new File((filePath));
File deFile = new File(outPath);
InputStream inputStream = null;
try {
inputStream = FileUtils.openInputStream(file);
} catch (IOException e) {
e.printStackTrace();
}
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream((new FileOutputStream(deFile)));
while ((inputStream.read(data)) != -1) {
decryptData = decryptByteArray(data);
bos.write(decryptData);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private byte[] decryptByteArray(byte[] input) {
Encryption e=new Encryption();
byte[]decryptedBytes = new byte[0];
try {
byte[] yourKey = e.generateKey("password");
decryptedBytes = e.decodeFile(yourKey, input);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} catch (Exception e1) {
e1.printStackTrace();
}
return decryptedBytes;
}
问题最有可能出现在这里:
while ((inputStream.read(data)) != -1) {
decryptData = decryptByteArray(data);
bos.write(decryptData);
}
当您读取一个长度不是 1024 字节倍数的文件时,最后一次读取不会完全填满字节数组,而是将整个数组传递给 decryptByteArray
。
另请注意,即使是中间读取,也不能保证 read
会完全填满数组。始终检查 return 值,它给出了实际读取的字节数。
问题没有说明加密是如何完成的。如果在密码中使用填充,则 1024 字节块的每次加密将比 1024 字节长(因为添加了填充块)。为了解密整个密文(包括填充)必须一次性处理。仅使用前 1024 个字节将导致 BadPaddingException
.
我正在尝试对视频和 pdf 进行加密。在我得到每个文件的流后,我分成缓冲区,然后我加密每个缓冲区并将所有缓冲区组合成一个加密文件。
对于加密,一切正常,但是当我尝试以相同的方式解密文件时,我在 doFinal 处遇到错误,即
{BadPaddingException : pad block corrupted BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:739)}
这是我正在测试的代码
加密
public static byte[] encodeFile(byte[] key, byte[] fileData) throws Exception
{
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(fileData);
return encrypted;
}
解密
public static byte[] decodeFile(byte[] key, byte[] fileData)
{
byte[] decrypted=new byte[0];
try {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
decrypted= cipher.doFinal(fileData);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
return decrypted;
}
生成密钥
public static byte[] generateKey(String password) throws Exception
{
byte[] keyStart = password.getBytes("UTF-8");
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
sr.setSeed(keyStart);
kgen.init(256, sr);
SecretKey skey = kgen.generateKey();
return skey.getEncoded();
}
这是我解密文件的方法
public void decryptStream(String filePath) {
String outPath = Environment.getExternalStorageDirectory().toString() + "/" + fileName + "de" + "." + fileExtention;
filePath += "_secured." + fileExtention;
byte[] data = new byte[1024];
byte[] decryptData;
File file = new File((filePath));
File deFile = new File(outPath);
InputStream inputStream = null;
try {
inputStream = FileUtils.openInputStream(file);
} catch (IOException e) {
e.printStackTrace();
}
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream((new FileOutputStream(deFile)));
while ((inputStream.read(data)) != -1) {
decryptData = decryptByteArray(data);
bos.write(decryptData);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private byte[] decryptByteArray(byte[] input) {
Encryption e=new Encryption();
byte[]decryptedBytes = new byte[0];
try {
byte[] yourKey = e.generateKey("password");
decryptedBytes = e.decodeFile(yourKey, input);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} catch (Exception e1) {
e1.printStackTrace();
}
return decryptedBytes;
}
问题最有可能出现在这里:
while ((inputStream.read(data)) != -1) {
decryptData = decryptByteArray(data);
bos.write(decryptData);
}
当您读取一个长度不是 1024 字节倍数的文件时,最后一次读取不会完全填满字节数组,而是将整个数组传递给 decryptByteArray
。
另请注意,即使是中间读取,也不能保证 read
会完全填满数组。始终检查 return 值,它给出了实际读取的字节数。
问题没有说明加密是如何完成的。如果在密码中使用填充,则 1024 字节块的每次加密将比 1024 字节长(因为添加了填充块)。为了解密整个密文(包括填充)必须一次性处理。仅使用前 1024 个字节将导致 BadPaddingException
.