解密图像时,给出 javax.crypto.BadPaddingException: pad block损坏的Android
您好,我是 android 和图像加密的新手.我的场景是这样的,
Hi i'm new to android and Image encryption. My scenario is like this,
- 首先我要加密图像文件.
- 那我上传到服务器
- 我正在从我的应用下载加密图像并将其保存在 SD 卡中.
- 然后我在将其设置为 imageView 之前对其进行解密
(我用过的所有需要方法见底部..)
(See bottom for all need methods I have used..)
但我得到 javax.crypto.BadPaddingException: 解密时垫块损坏.我读了一些关于这个例外的文章,但都是关于文本加密的.你能帮我避免这种情况吗?提前谢谢你
图像加密使用 ...
private byte[] encrypt(byte[] raw, byte[] clear) throws Exception
{
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
这里我也保存了其他几张图片,都成功保存到了sd卡中...
Here I'm saving several other images as well, all saved in sd card successfully...
for (int i = 0; i < imageUrls.size(); i++)
{
File file = new File(imageUrls.get(i));
String metapath = CommonUtils.getDataFromPreferences("metaPath", "");
Log.d("metapath", metapath);
String extStorageDirectory = metapath + file.getName();
File wallpaperDirectory = new File(extStorageDirectory);
if (!wallpaperDirectory.exists() || wallpaperDirectory.length() == 0)
{
new DownloadImagesTask()
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, imageUrls.get(i));
}
}
Toast toast = Toast.makeText(ScratchDetailsActivity.this, "Lottery was purchased and saved to sdcard/E-Lottery",
Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
图像解密...
这里的解密文件第一个参数是密钥,第二个是我们从 SD 卡获取的加密文件.
decrypt the file here first argument is key and second is encrypted file which we get from SD card.
decrpt = simpleCrypto.decrypt(KEY, getImageFileFromSdCard());
bmpimg2 = BitmapFactory.decodeByteArray(decrpt, 0, decrpt.length);
Drawable d = new BitmapDrawable(getResources(), bmpimg2);
hiddenImage.setImageDrawable(d);
下载图像任务..
public class DownloadImagesTask extends AsyncTask<String, Void, InputStream>{
private String fileName;
@Override
protected InputStream doInBackground(String... urls)
{
//Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
return download_Image(urls[0]);
}
@Override
protected void onPostExecute(InputStream result)
{
storeImage(result);
}
private InputStream download_Image(String url)
{
InputStream is = null;
File file = new File(url);
fileName = file.getName();
try
{
URL aURL = new URL(url);
URLConnection conn = aURL.openConnection();
conn.connect();
is = conn.getInputStream();
}
catch (OutOfMemoryError e)
{
Log.e("Hub", "Error getting the image from server : " + e.getMessage().toString());
}
catch (IOException e)
{
Log.e("Hub", "Error getting the image from server : " + e.getMessage().toString());
}
return is;
}
public void storeImage(InputStream is)
{
String extStorageDirectory = CommonUtils.getDataFromPreferences("metaPath", "");
Log.d("extStorageDirectory", extStorageDirectory);
OutputStream outStream = null;
File wallpaperDirectory = new File(extStorageDirectory);
if (!wallpaperDirectory.exists())
{
wallpaperDirectory.mkdirs();
}
File outputFile = new File(wallpaperDirectory, fileName);
if (!outputFile.exists() || outputFile.length() == 0)
{
try
{
outStream = new FileOutputStream(outputFile);
}
catch (FileNotFoundException e1)
{
e1.printStackTrace();
}
try
{
int bytesRead = -1;
byte[] buffer = new byte[4096];
while ((bytesRead = is.read(buffer)) != -1)
{
outStream.write(buffer, 0, bytesRead);
}
outStream.close();
is.close();
Log.d("ScratchActivtiy", "Image Saved");
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}}
getImageFileFromSDCard 方法
getImageFileFromSDCard method
/**
* This method fetch encrypted file which is save in sd card and convert it in byte array after that this file will
* be decrept.
*
* @return byte array of encrypted data for decription.
* @throws FileNotFoundException
*/
public byte[] getImageFileFromSdCard() throws FileNotFoundException
{
byte[] inarry = null;
try
{
String metapath = CommonUtils.getDataFromPreferences("metaPath", "");
File imageFolder = new File(metapath);
File urlFile = new File(selectedLottery.getImage());
for (File f : imageFolder.listFiles())
{
if (urlFile.getName().equals(f.getName()))
metapath = metapath + f.getName();
}
File imageFile = new File(metapath);
//Convert file into array of bytes.
FileInputStream fileInputStream = null;
byte[] bFile = new byte[(int) imageFile.length()];
fileInputStream = new FileInputStream(imageFile);
fileInputStream.read(bFile);
fileInputStream.close();
inarry = bFile;
}
catch (IOException e)
{
Log.d("Exception", e.getMessage());
}
return inarry;
}
推荐答案
有很多事情可能会导致 Bad Padding 异常.要检查的明显事项是您正在使用的加密和解密:
There are a lot of things that might cause a Bad Padding exception. Obvious things to check are that for both encryption and decryption you are using:
相同的key,即逐字节相同.
the same key, that is byte-for-byte the same.
相同的加密模式(通常是 CBC、CTR 或 GCM).
the same encryption mode (CBC, CTR or GCM usually).
相同的 IV/Nonce,再次逐字节相同.
the same IV/Nonce, again byte-for-byte the same.
相同的填充(PKCS5 或 PKCS7 很常见).
the same padding (PKCS5 or PKCS7 are common).
不要依赖系统默认值,尤其是在一个系统上加密并在另一个系统上解密时,就像您似乎正在做的那样.如果系统默认值不同,那么您的解密将失败.始终明确设置键、模式、IV 和填充.在任何合理的加密库中都会有记录的方法.
Do not rely on system defaults, especially when encrypting on one system and decrypting on another, as you seem to be doing. If the system defaults are different, then your decryption will fail. Always explicitly set key, mode, IV and padding. There will be documented ways to do so in any reasonable crypto library.
如果这不能解决问题,那么您将需要做更多的挖掘工作.将解密方法临时设置为 NoPadding
或您的库使用的任何等效方法.这将使解密方法忽略填充错误,并为您提供一些输出.查看输出并将其与原始输入进行比较;您可能需要查看此处的十六进制转储以确定发生了什么.
If that doesn't solve it then you will need to do a bit more digging. Set the decryption method temporarily to NoPadding
or whatever equivalent your library uses. That will let the decryption method ignore padding errors, and give you some output. Have a look at the output and compare it to the original input; you may have to look at hex dumps here to be sure what is happening.
其中的可能性有:
输出完全是垃圾:您的密钥错误,或者 IV/Nonce对于流密码或 GCM 模式或 CTR 模式是错误的.
the output is complete garbage: your key is wrong, or the IV/Nonce is wrong for a stream cypher or GCM mode or CTR mode.
第一个块是垃圾,其余的与明文匹配:你在 CBC 模式下输入错误的 IV.
the first block is garbage with the rest matching the plaintext: you have the wrong IV in CBC mode.
输出最后匹配了一些额外的东西:额外的东西是填充.将您的解密方法设置为期望该类型的填充.
the output matches with some extra stuff at the end: the extra stuff is padding. Set your decryption method to expect that type of padding.
如果这些都没有发生,请在此处再次询问并描述症状.
If none of these happen, then ask again here, describing the symptoms.
当您找到解决方案后,您必须将您的解密方法重新设置为期望正确的填充.将其设置为 NoPadding
是不安全的,因为任何旧垃圾都可以添加到解密的明文中.
When you have got a solution, you must set your decryption method back to expect the correct padding. Leaving it set to NoPadding
is not secure since any old garbage can be added to the decrypted plaintext.
相关文章