1

I'm new to android. I'm doing an application which can download an encrypted png image file to sd card then displaying it after decryption. But I notice that I'm getting "javax.crypto.IllegalBlockSizeException: last block incomplete in decryption image decryption" when decrypting that downloaded image. Then I found that downloaded image size is 0KB (Original - 150KB). Then I downloaded my encrypted image from browser and checked. I'm getting the original image size. I'm sure there is something wrong in my image downloading class. But I cant figure it out. Please help me. Thanks in advance.

Image downloading AsyncTask Class

public class DownloadImagesTask extends AsyncTask<String, Void, Bitmap>
{
    private String fileName;

    @Override
    protected Bitmap doInBackground(String... urls)
    {
        //Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
        return download_Image(urls[0]);
    }

    @Override
    protected void onPostExecute(Bitmap result)
    {
        storeImage(result);

    }

    private Bitmap download_Image(String url)
    {
        Bitmap bm = null;
        File file = new File(url);
        fileName = file.getName();
        try
        {
            URL aURL = new URL(url);
            URLConnection conn = aURL.openConnection();
            conn.connect();
            InputStream is = conn.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is);
            bm = BitmapFactory.decodeStream(bis);
            bis.close();
            is.close();
        }
        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 bm;
    }

    public void storeImage(Bitmap bm)
    {
        BitmapFactory.Options bmOptions;
        bmOptions = new BitmapFactory.Options();
        bmOptions.inSampleSize = 1;
        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
            {
                bm.compress(Bitmap.CompressFormat.PNG, 100, outStream);
                outStream.flush();
                outStream.close();
                Log.d("ScratchActivtiy", "Image Saved");

            }
            catch (FileNotFoundException e)
            {
                e.printStackTrace();

            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}

(All images were encrypted by me. And I hosted them in a Server. There is no issue in ancryption or decryption. I tested them. All are working fine.)

CryptClass

public class CryptClass
{

    public byte[] encrypt(String seed, byte[] cleartext) throws Exception
    {

        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] result = encrypt(rawKey, cleartext);
        //  return toHex(result);
        return result;
    }

    public byte[] decrypt(String seed, byte[] encrypted) throws Exception
    {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] enc = encrypted;
        byte[] result = decrypt(rawKey, enc);

        return result;
    }

    //done
    private byte[] getRawKey(byte[] seed) throws Exception
    {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        sr.setSeed(seed);
        kgen.init(128, sr);
        SecretKey skey = kgen.generateKey();
        byte[] raw = skey.getEncoded();
        return raw;
    }

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

    private byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception
    {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] decrypted = cipher.doFinal(encrypted);
        return decrypted;
    }
}
4

1 回答 1

2

If I understand correctly you are downloading the image first

BufferedInputStream bis = new BufferedInputStream(is);
bm = BitmapFactory.decodeStream(bis);

Then saving it to a file with PNG compression:

bm.compress(Bitmap.CompressFormat.PNG, 100, outStream);

And AFTER that doing your decryption on the file, right?

I think you might want to decrypt the bytes prior to saving them as a png, or maybe even prior to using the decodeStream. Otherwise you are decrypting the encrypted bytes that decode stream and PNG compression messed with.

Try skipping all of the BitmapFactory stuff and just save the initial file as-is, and then run your decryption. In your AsyncTask:

String saveFilePath = <path to the temporary encrypted file>;

FileOutputStream outputStream = new FileOutputStream(saveFilePath);
int bytesRead = -1;
byte[] buffer = new byte[4096];
while ((bytesRead = is.read(buffer)) != -1) {
    outputStream.write(buffer, 0, bytesRead);
}

outputStream.close();
inputStream.close();

Then run your decryption stuff on the saved file

于 2013-08-19T17:54:41.560 回答