問題描述
您好,我是 android 和圖像加密的新手.我的場(chǎng)景是這樣的,
Hi i'm new to android and Image encryption. My scenario is like this,
- 首先我要加密圖像文件.
- 那我上傳到服務(wù)器
- 我正在從我的應(yīng)用下載加密圖像并將其保存在 SD 卡中.
- 然后我在將其設(shè)置為 imageView 之前對(duì)其進(jìn)行解密
(我用過的所有需要??方法見底部..)
(See bottom for all need methods I have used..)
但我得到 javax.crypto.BadPaddingException: 解密時(shí)墊塊損壞.我讀了一些關(guān)于這個(gè)例外的文章,但都是關(guān)于文本加密的.你能幫我避免這種情況嗎?提前謝謝你
圖像加密使用 ...
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();
圖像解密...
這里的解密文件第一個(gè)參數(shù)是密鑰,第二個(gè)是我們從 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);
下載圖像任務(wù)..
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;
}
推薦答案
有很多事情可能會(huì)導(dǎo)致 Bad Padding 異常.要檢查的明顯事項(xiàng)是您正在使用的加密和解密:
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,即逐字節(jié)相同.
the same key, that is byte-for-byte the same.
相同的加密模式(通常是 CBC、CTR 或 GCM).
the same encryption mode (CBC, CTR or GCM usually).
相同的 IV/Nonce,再次逐字節(jié)相同.
the same IV/Nonce, again byte-for-byte the same.
相同的填充(PKCS5 或 PKCS7 很常見).
the same padding (PKCS5 or PKCS7 are common).
不要依賴系統(tǒng)默認(rèn)值,尤其是在一個(gè)系統(tǒng)上加密并在另一個(gè)系統(tǒng)上解密時(shí),就像您似乎正在做的那樣.如果系統(tǒng)默認(rèn)值不同,那么您的解密將失敗.始終明確設(shè)置鍵、模式、IV 和填充.在任何合理的加密庫中都會(huì)有記錄的方法.
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.
如果這不能解決問題,那么您將需要做更多的挖掘工作.將解密方法臨時(shí)設(shè)置為 NoPadding
或您的庫使用的任何等效方法.這將使解密方法忽略填充錯(cuò)誤,并為您提供一些輸出.查看輸出并將其與原始輸入進(jìn)行比較;您可能需要查看此處的十六進(jìn)制轉(zhuǎn)儲(chǔ)以確定發(fā)生了什么.
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.
其中的可能性有:
輸出完全是垃圾:您的密鑰錯(cuò)誤,或者 IV/Nonce對(duì)于流密碼或 GCM 模式或 CTR 模式是錯(cuò)誤的.
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.
第一個(gè)塊是垃圾,其余的與明文匹配:你在 CBC 模式下輸入錯(cuò)誤的 IV.
the first block is garbage with the rest matching the plaintext: you have the wrong IV in CBC mode.
輸出最后匹配了一些額外的東西:額外的東西是填充.將您的解密方法設(shè)置為期望該類型的填充.
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.
如果這些都沒有發(fā)生,請(qǐng)?jiān)诖颂幵俅卧儐柌⒚枋霭Y狀.
If none of these happen, then ask again here, describing the symptoms.
當(dāng)您找到解決方案后,您必須將您的解密方法重新設(shè)置為期望正確的填充.將其設(shè)置為 NoPadding
是不安全的,因?yàn)槿魏闻f垃圾都可以添加到解密的明文中.
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.
這篇關(guān)于解密圖像時(shí),給出 javax.crypto.BadPaddingException: pad block損壞的Android的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!