本文介绍了解密时的图像,使javax.crypto.BadPaddingException:垫块损坏的Andr​​oid的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新来的Andr​​oid和图像加密。我的情况是这样的,

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

(适用于所有需要的方法我都用过见底。)

但是我却越来越javax.crypto.BadPaddingException:解密时垫块损坏。我读到此异常的一些文章,但都是关于文本加密。你能帮我避免这种情况。谢谢你在前进

使用图片Encrption ...

 私人byte []的加密(byte []的原料,byte []的明确的)抛出异常
{
    SecretKeySpec skeySpec =新SecretKeySpec(原AES);
    密密码= Cipher.getInstance(AES);
    cipher.init(Cipher.ENCRYPT_MODE,skeySpec);
    byte []的加密= cipher.doFinal(清晰);
    返回加密;
}
 

在这里,我节省了其他几个图像以及所有保存在SD卡的成功...

 的for(int i = 0; I< imageUrls.size();我++)
                {
                    档案文件=新的文件(imageUrls.get(一));

                    字符串metapath = CommonUtils.getDataFrom preferences(metaPath,);
                    Log.d(metapath,metapath);
                    串extStorageDirectory = metapath + file.getName();

                    文件wallpaperDirectory =新的文件(extStorageDirectory);
                    如果(!wallpaperDirectory.exists()|| wallpaperDirectory.length()== 0)
                    {
                        新DownloadImagesTask()
                            .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,imageUrls.get(I));
                    }
                }
                吐司面包= Toast.makeText(ScratchDetailsActivity.this,彩票被购买并保存到SD卡/ E-彩票,
                    Toast.LENGTH_LONG);
                toast.setGravity(Gravity.CENTER,0,0);
                toast.show();
 

图像解密...

解密文件在这里第一个参数是关键,二是加密的,我们从SD卡获取文件。

  decrpt = simpleCrypto.decrypt(KEY,getImageFileFromSdCard());
        bmpimg2 = BitmapFactory.de codeByteArray(decrpt,0,decrpt.length);
        绘制对象D =新BitmapDrawable(getResources(),bmpimg2);
        hiddenImage.setImageDrawable(四);
 

DownloadImageTask ..

 公共类DownloadImagesTask扩展的AsyncTask<字符串,无效的InputStream> {
私人字符串文件名;

@覆盖
受保护的InputStream doInBackground(字符串...网址)
{
    //Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
    返回download_Image(网址[0]);
}

@覆盖
保护无效onPostExecute(InputStream的结果)
{
    storeImage(结果);

}

私人的InputStream download_Image(字符串URL)
{
    InputStream的是= NULL;
    档案文件=新的文件(URL);
    文件名= file.getName();
    尝试
    {
        URL aURL =新的网址(URL);
        URLConnection的康恩= aURL.openConnection();
        conn.connect();
        是= conn.getInputStream();
    }
    赶上(OutOfMemoryError异常E)
    {
        Log.e(集线器,错误获取的图像从服务器:+ e.getMessage()的toString());
    }
    赶上(IOException异常E)
    {
        Log.e(集线器,错误获取的图像从服务器:+ e.getMessage()的toString());
    }

    回报;
}

公共无效storeImage(InputStream的是)
{

    字符串extStorageDirectory = CommonUtils.getDataFrom preferences(metaPath,);

    Log.d(extStorageDirectory,extStorageDirectory);
    OutputStream的outStream = NULL;

    文件wallpaperDirectory =新的文件(extStorageDirectory);
    如果(!wallpaperDirectory.exists())
    {
        wallpaperDirectory.mkdirs();
    }
    文件OUTPUTFILE =新的文件(wallpaperDirectory,文件名);
    如果(!outputFile.exists()|| outputFile.length()== 0)
    {
        尝试
        {
            outStream =新的FileOutputStream(OUTPUTFILE);
        }
        赶上(FileNotFoundException异常E1)
        {
            e1.printStackTrace();
        }

        尝试
        {
            INT读取动作= -1;
            byte []的缓冲区=新的字节[4096];
            而((读取动作= is.​​read(缓冲液))!=  -  1)
            {
                outStream.write(缓冲液,0,读取动作);
            }

            outStream.close();
            is.close();
            Log.d(ScratchActivtiy,图像保存);

        }
        赶上(FileNotFoundException异常E)
        {
            e.printStackTrace();

        }
        赶上(IOException异常E)
        {
            e.printStackTrace();
        }
        赶上(例外五)
        {
            e.printStackTrace();
        }
    }
}}
 

getImageFileFromSDCard方法

  / **
     *这个方法获取加密的文件,该文件是保存在SD卡,之后转换的字节数组这个文件将
     *可decrept。
     *
     *加密数据能解密的@返回字节数组。
     * @throws FileNotFoundException异常
     * /

公共字节[] getImageFileFromSdCard()抛出FileNotFoundException异常
{

    byte []的inarry = NULL;

    尝试
    {
        字符串metapath = CommonUtils.getDataFrom preferences(metaPath,);

        文件imageFolder =新的文件(metapath);
        文件urlFile =新的文件(selectedLottery.getImage());

        对于(文件F:imageFolder.listFiles())
        {
            如果(urlFile.getName()。等于(f.getName()))
                metapath = metapath + f.getName();
        }
        文件镜像文件=新的文件(metapath);
        //将文件转换成字节数组。
        的FileInputStream的FileInputStream = NULL;
        byte []的BFILE =新的字节[(INT)imageFile.length()];
        的FileInputStream =新的FileInputStream(镜像文件);
        fileInputStream.read(BFILE);
        fileInputStream.close();
        inarry = BFILE;

    }
    赶上(IOException异常E)
    {
        Log.d(异常,e.getMessage());
    }

    返回inarry;
}
 

解决方案

有很多事情可能会导致不良填充异常。明显的事情要检查是用于加密和解密使用的是:

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

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

  3. 同样IV /随机数,再字节为字节相同。

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

不要依赖于系统默认值,在一个系统上加密和解密的另一尤其是当你似乎做的事情。如果系统默认值是不同的,那么你的解密会失败。始终明确设置键,模式,IV和填充。有将被记录的方式来这样做的任何合理的加密库

如果不解决这个问题,那么你就需要做更多的挖掘。临时设置解密方法 NoPadding 或其他等效的库使用。这将让解密方法忽略填充错误,并给你一些输出。看一看输出,并将其与原来的输入;你可能看十六进制转储这里一定发生了什么。

其中的可能性是:

  1. 输出完整的垃圾:你的关键是错误的,或者IV /杜撰是错误的流暗号或GCM模式或CTR模式。

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

  3. 并在后面加上一些额外的东西输出匹配:多余的东西是填充。设置你的解密方法,以期望类型填充。

如果没有这些情况发生,那么再问这里,描述的症状。

当你有一个解决方案,您必须设置您的解密方法回期望正确的填充。离开它设置为 NoPadding 是不安全的,因为任何旧的垃圾可以添加到解密后的明文。

Hi i'm new to android and Image encryption.My scenario is like this,

  • first I'm encrypting the image file.
  • Then I'm uploading it to the Server
  • From my app I'm downloading encrypted image and saving it in SD card.
  • then I'm decrypting it before set it to the imageView

(See bottom for all need methods I have used..)

But I'm getting javax.crypto.BadPaddingException: pad block corrupted when decrypting. I read some articles about this exception but all are about text encryption. Can you help me to avoid this. Thank you in advance

Image Encrption using ...

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;
}

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();

Image decryption...

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);

DownloadImageTask..

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 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;
}
解决方案

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:

  1. the same key, that is byte-for-byte the same.

  2. the same encryption mode (CBC, CTR or GCM usually).

  3. the same IV/Nonce, again byte-for-byte the same.

  4. the same padding (PKCS5 or PKCS7 are common).

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.

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.

Among the possibilities are:

  1. the output is complete garbage: your key is wrong, or the IV/Nonceis wrong for a stream cypher or GCM mode or CTR mode.

  2. the first block is garbage with the rest matching the plaintext: youhave the wrong IV in CBC mode.

  3. the output matches with some extra stuff at the end: the extra stuffis padding. Set your decryption method to expect that type ofpadding.

If none of these happen, then ask again here, describing the symptoms.

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.

这篇关于解密时的图像,使javax.crypto.BadPaddingException:垫块损坏的Andr​​oid的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-13 13:25