Android 安卓AES解密文件:BadPaddingException:EVP\u CipherFinal\u ex
我最近正在研究文件加密/解密 BadPaddingException:EVP_CipherFinal_ex:总是在我尝试使用相同密钥解密文件时发生 代码片段将发布在下面 我做错什么了吗 谢谢你的帮助 加密Android 安卓AES解密文件:BadPaddingException:EVP\u CipherFinal\u ex,android,encryption,cryptography,Android,Encryption,Cryptography,我最近正在研究文件加密/解密 BadPaddingException:EVP_CipherFinal_ex:总是在我尝试使用相同密钥解密文件时发生 代码片段将发布在下面 我做错什么了吗 谢谢你的帮助 加密 public static void encryptFile() { File file = new File(Environment.getExternalStorageDirectory().getPath() + "/" + TARGET_FILE); FileInpu
public static void encryptFile() {
File file = new File(Environment.getExternalStorageDirectory().getPath() + "/" + TARGET_FILE);
FileInputStream fileInputStream;
FileOutputStream fileOutputStream;
byte[] buffer = new byte[1024 * 8];
IvParameterSpec ivParameterSpec = new IvParameterSpec("1234567890123456".getBytes());
byte[] key = "only for testing".getBytes();
MessageDigest sha;
try {
sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
key = Arrays.copyOf(key, 16); // use only first 128 bit
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
try {
fileInputStream = new FileInputStream(file);
fileOutputStream = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + "/" + ENCRYPT_FILE);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
//CipherOutputStream cipherOutputStream = new CipherOutputStream(fileOutputStream, cipher);
int read;
while ((read = fileInputStream.read(buffer)) > 0) {
Log.i(TAG, "encrypt read= " + read);
byte[] encryptedData = cipher.doFinal(buffer);
if (encryptedData != null) {
Log.i(TAG, "encrypted size= " + encryptedData.length);
fileOutputStream.write(encryptedData, 0, read);
}
//cipherOutputStream.write(buffer, 0, buffer.length);
}
//cipherOutputStream.flush();
//cipherOutputStream.close();
fileInputStream.close();
fileOutputStream.close();
} catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException
| IllegalBlockSizeException | BadPaddingException
| InvalidAlgorithmParameterException | InvalidKeyException e) {
e.printStackTrace();
}
}
解密
public static void decryptFile() {
File file = new File(Environment.getExternalStorageDirectory().getPath() + "/" + ENCRYPT_FILE);
FileInputStream fileInputStream;
FileOutputStream fileOutputStream;
byte[] buffer = new byte[1024 * 8];
IvParameterSpec ivParameterSpec = new IvParameterSpec("1234567890123456".getBytes());
byte[] key = "only for testing".getBytes();
MessageDigest sha;
try {
sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
key = Arrays.copyOf(key, 16); // use only first 128 bit
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
try {
fileInputStream = new FileInputStream(file);
fileOutputStream = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + "/" + DECRYPT_FILE);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
//CipherInputStream cipherInputStream = new CipherInputStream(fileInputStream, cipher);
int read;
while ((read = fileInputStream.read(buffer)) > 0) {
Log.i(TAG, "decrypt read= " + read);
byte[] decryptedData = cipher.doFinal(buffer);
if (decryptedData != null) {
Log.i(TAG, "decrypted size= " + decryptedData.length);
fileOutputStream.write(decryptedData, 0, read);
}
//fileOutputStream.write(buffer, 0, buffer.length);
}
fileOutputStream.flush();
fileOutputStream.close();
//cipherInputStream.close();
fileInputStream.close();
} catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException
| IllegalBlockSizeException | BadPaddingException
| InvalidAlgorithmParameterException | InvalidKeyException e) {
e.printStackTrace();
}
}
顺便说一句:当我使用CipherInputStream/CipherOutStream时,它会正常工作。我想知道是否可以只使用FileInputStream/FileOutputStream?多谢各位
编辑:
加密函数会将字节数组放大约16个字节,我已尝试增加解密的缓冲区大小,但仍然无法使其工作
byte[] buffer = new byte[1024 * 8 + 16];
日志:
I/##:解密读取=8208
javax.crypto.BadPaddingException:EVP\u CipherFinal\u ex
在com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(本机方法)
访问com.android.org.conscrypt.OpenSSLCipher.doFinalInternal(OpenSSLCipher.java:430)
位于com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:466)
位于javax.crypto.Cipher.doFinal(Cipher.java:1340)
位于CryptoHelper.decryptohelper文件(CryptoHelper.java:128)
编辑了根据#Robert的答案,为遇到与我相同问题的人更新代码
加密:
int read;
while ((read = fileInputStream.read(buffer)) > 0) {
Log.i(TAG, "encrypt read= " + read);
byte[] encryptedData = cipher.update(buffer, 0, read);
//byte[] encryptedData = cipher.doFinal(buffer);
if (encryptedData != null) {
Log.i(TAG, "encrypted size= " + encryptedData.length);
fileOutputStream.write(encryptedData, 0, encryptedData.length);
}
//cipherOutputStream.write(buffer, 0, buffer.length);
}
byte[] finals = cipher.doFinal();
Log.i(TAG, "encrypted finals = " + finals.length);
fileOutputStream.write(finals, 0, finals.length);
解密:
int read;
while ((read = fileInputStream.read(buffer)) > 0) {
Log.i(TAG, "decrypt read= " + read);
//byte[] decryptedData = cipher.doFinal(buffer);
byte[] decryptedData = cipher.update(buffer, 0, read);
if (decryptedData != null) {
Log.i(TAG, "decrypted size= " + decryptedData.length);
fileOutputStream.write(decryptedData, 0, decryptedData.length);
}
//fileOutputStream.write(buffer, 0, buffer.length);
}
byte[] finals = cipher.doFinal();
Log.i(TAG, "decrypted finals = " + finals.length);
fileOutputStream.write(finals, 0, finals.length);
再次感谢Robert的帮助。您的问题是,您总是为每个错误的数据块调用
cipher.doFinal()
,因为每个数据块都将被填充
如果您正在对数据块进行加密/解密,请使用cipher.update(…)
并在处理最后一个数据块后只调用cipher.doFinal()
一次
更简单的方法是使用CipherInputStream/CipherOutputStream-它完全符合我为您描述的功能(关闭流时调用doFinal)。您的问题是,您总是为每个错误的数据块调用
cipher.doFinal()
,因为每个数据块都将被填充
如果您正在对数据块进行加密/解密,请使用cipher.update(…)
并在处理最后一个数据块后只调用cipher.doFinal()
一次
更简单的方法是使用CipherInputStream/CipherOutputStream——它完全符合我为您描述的内容(关闭流时会调用doFinal)。我按照您的答案编辑了代码。现在可以了。非常感谢你的帮助。你救了我一天。我按照你的答案编辑了代码。现在可以了。非常感谢你的帮助。你救了我一天。