【问题标题】:How to download an encrypted png file without loosing data?如何在不丢失数据的情况下下载加密的 png 文件?
【发布时间】:2013-08-20 02:12:44
【问题描述】:

我是安卓新手。我正在做一个应用程序,它可以将加密的 png 图像文件下载到 sd 卡,然后在解密后显示它。但我注意到在解密下载的图像时我得到了“javax.crypto.IllegalBlockSizeException: last block incomplete in decryption image decryption”。然后我发现下载的图像大小为 0KB(原始 - 150KB)。然后我从浏览器下载我的加密图像并检查。我正在获取原始图像大小。我确定我的图像下载课程有问题。但我想不通。请帮我。提前致谢。

图片下载AsyncTask类

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

(所有图像均由我加密。我将它们托管在服务器中。加密或解密没有问题。我测试了它们。一切正常。)

地穴类

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

【问题讨论】:

  • 我在您发布的内容中没有看到任何加密代码,只是下载图像并将其直接传递给BitmapFactory
  • 是的。我的加密代码工作正常。但是当我从服务器下载该加密图像时,它已作为 0kb png 文件下载到 SD 卡中。下载该图像时发生了一些事情,我无法弄清楚。

标签: android encryption imagedownload


【解决方案1】:

如果我理解正确,您是先下载图像

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

然后用PNG压缩保存到文件中:

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

在对文件进行解密之后,对吗?

我认为您可能希望在将字节保存为 png 之前或什至在使用 decodeStream 之前对其进行解密。否则,您将解密解码流和 PNG 压缩的加密字节。

尝试跳过所有 BitmapFactory 内容并按原样保存初始文件,然后运行解密。在您的 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();

然后在保存的文件上运行你的解密内容

【讨论】:

  • 就像这样.. 我想下载并保存文件,因为它是加密格式的。后来我解密了。见.. 我也附上了我的 CryptClass。有一个要求,即使从文件管理器中也看不到文件。
  • 我明白,我的意思是您正在下载加密文件,然后使用 PNG 压缩保存它,这很可能会更改您的文件内容。然后,您尝试对其进行解密,但失败了,因为文件字节不再是您的解密可以理解的内容。
  • 好的。那我该如何解决。有什么办法可以把它以加密格式保存在 SD 卡中。?
猜你喜欢
  • 2014-02-04
  • 2012-09-26
  • 1970-01-01
  • 2021-09-03
  • 2017-04-07
  • 2023-03-18
  • 2014-06-18
  • 2021-08-19
  • 1970-01-01
相关资源
最近更新 更多