当Decrypting Image时,给出了javax.crypto.BadPaddingException:pad块损坏的Android

嗨,我是Android和图像加密的新手。 我的情况是这样的,

  • 首先,我正在加密图像文件。
  • 然后我将它上传到服务器
  • 从我的应用程序我下载加密图像并将其保存在SD卡中。
  • 然后我在将它设置为imageView之前解密它

(请参阅我已经使用的所有需要​​方法的底部..)

但我得到javax.crypto.BadPaddingException:解密时pad块损坏。 我读了一些关于这个例外的文章,但都是关于文本加密的。 你能帮我避免这个吗? 先感谢您

Image Encrption使用…

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卡中…

 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卡获得的加密文件。

  decrpt = simpleCrypto.decrypt(KEY, getImageFileFromSdCard()); bmpimg2 = BitmapFactory.decodeByteArray(decrpt, 0, decrpt.length); Drawable d = new BitmapDrawable(getResources(), bmpimg2); hiddenImage.setImageDrawable(d); 

DownloadImageTask ..

 public class DownloadImagesTask extends AsyncTask{ 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方法

 /** * 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 Paddingexception。 要检查的明显事项是您正在使用的加密和解密:

  1. 相同的密钥,即逐字节相同。

  2. 相同的加密模式(通常为CBC,CTR或GCM)。

  3. 相同的IV / Nonce,再次逐字节相同。

  4. 相同的填充(PKCS5或PKCS7是常见的)。

不要依赖系统默认值,特别是在一个系统上加密和在另一个系统上解密时,就像你似乎在做的那样。 如果系统默认值不同,则解密将失败。 始终明确设置键,模式,IV和填充。 在任何合理的加密库中都会有记录的方法。

如果这没有解决它,那么你将需要做更多的挖掘。 将解密方法临时设置为NoPadding或您的库使用的任何等效方法。 这将使解密方法忽略填充错误,并为您提供一些输出。 查看输出并将其与原始输入进行比较; 你可能需要在这里查看hex转储以确定发生了什么。

其中的可能性包括:

  1. 输出是完全垃圾:您的密钥错误,或者流/密码或GCM模式或CTR模式的IV / Nonce错误。

  2. 第一个块是垃圾,其余块与明文匹配:你在CBC模式下有错误的IV。

  3. 输出与最后的一些额外的东西匹配:额外的东西是填充。 设置解密方法以期望填充类型。

如果这些都没有发生,那么请在这里再次询问,描述症状。

获得解决方案后, 必须重新设置解密方法以获得正确的填充。 将其设置为NoPadding是不安全的,因为任何旧垃圾都可以添加到解密的明文中。