Xamarin.android-如何更快地加密/解密图像 [英] Xamarin.android- how to make encryption/decryption of images faster

查看:17
本文介绍了Xamarin.android-如何更快地加密/解密图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望用户从图库中选择图像/视频并在我的应用中保护他们的图像.为此,我加密了这些图像.对图像的加密工作正常(我认为是这样!).8MB 图像需要 1.5 到 2 秒.但是视频呢?视频可能以 GB 为单位.所以会花很多时间.即使在加密/解密中,我也必须对每个图像执行操作,这可能会导致内存问题.

I want users to select images/videos from gallery and secure their images within my app. for that, I encrypt those images. Encryption over images works correctly(I think so !). It takes 1.5 to 2 seconds for 8MB image. but what about videos ? videos might be in GBs. So it would take a lot time. And even in encryption/decryption I have to perform action on every single image, that can cause memory issue. This link helped me to achieve this.

If you see, ES file explorer also provides encryption and decryption on images/videos. and it completes operation of GBs within just few seconds. So can I know which technique/algorithm these guys use ?

or even if I use my own way, is there any trick to make it faster ? or is there any other way to make file inaccessible to user ? Changing MIME type will work ?

Even if I change extension or make it hidden by adding . before the file name, user can still view images in some file explorer.

Actually for xamarin, I didn't find any post/blog related to encrypting decrypting file. All they provide is solution on string.

i would really appreciate if someone guides me for this issue.

EDIT

Hello, @Joe Lv, As I said I tried your method in which encryption was slow but decryption was very fast. So I implemented the same decryption technique you used to encrypt things. And It works !! but I want to know if this is valid or not.

Now my encrypt method looks like this :

public void encrypt(string filename)
    {

        // Here you read the cleartext.
        try
        {
            File extStore = Environment.GetExternalStoragePublicDirectory(Environment.DirectoryMovies);
            startTime = System.DateTime.Now.Millisecond;
            Android.Util.Log.Error("Encryption Started", extStore + "/" + filename);

            // This stream write the encrypted text. This stream will be wrapped by
            // another stream.
        //    createFile(filename, extStore);
        //    System.IO.FileStream fs=System.IO.File.OpenRead(extStore + "/" + filename);
      //      FileOutputStream fos = new FileOutputStream(extStore + "/" + filename + ".aes", false);

            FileInputStream fis = new FileInputStream(filepath);


            FileOutputStream fos = new FileOutputStream(filepath, false);
            System.IO.FileStream fs = System.IO.File.OpenWrite(filepath + filename);
            // Create cipher

            // Length is 16 byte
            Cipher cipher = Cipher.GetInstance("AES/CBC/PKCS5Padding");
            byte[] raw = System.Text.Encoding.Default.GetBytes(sKey);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            IvParameterSpec iv = new IvParameterSpec(System.Text.Encoding.Default.GetBytes(ivParameter));//
            cipher.Init(CipherMode.EncryptMode, skeySpec, iv);

            // Wrap the output stream
           // CipherInputStream cis = new CipherInputStream(fs, cipher);
            CipherOutputStream cos = new CipherOutputStream(fs, cipher);

            // Write bytes
            int b;
            byte[] d = new byte[512 * 1024];
            while ((b = fis.Read(d)) != -1)
            {
                cos.Write(d, 0, b);
            }
            // Flush and close streams.
            fos.Flush();
            fos.Close();
            cos.Close();
   fis.Close();

            stopTime = System.DateTime.Now.Millisecond;
            Android.Util.Log.Error("Encryption Ended", extStore + "/5mbtest/" + filename + ".aes");
            Android.Util.Log.Error("Time Elapsed", ((stopTime - startTime) / 1000.0) + "");
        }
        catch (Exception e)
        {
            Android.Util.Log.Error("lv",e.Message);
        }

    }

解决方案

I didn't find any post/blog related to encrypting decrypting file

You can use CipherOutputStream and CipherInputStream to achieve it.

Here is my test demo, you can try it, and you need push a video file named videoplayback.mp4 into your phone which path is /storage/sdcard/Movies, so you can test my code directly.

using Android.App;
using Android.Widget;
using Android.OS;
using Javax.Crypto.Spec;
using Java.Lang;
using Java.IO;
using Javax.Crypto;
using System.Text;

namespace EncryTest
{
    [Activity(Label = "EncryTest", MainLauncher = true)]
    public class MainActivity : Activity
    {
        long stopTime, startTime;
        private string sKey = "0123456789abcdef";//key,
        private string ivParameter = "1020304050607080";
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);

            encrypt("videoplayback.mp4");
            decrypt("videoplayback.mp4");
        }

        public void encrypt(string filename)
        {

            // Here you read the cleartext.
            try
            {
                File extStore = Environment.GetExternalStoragePublicDirectory(Environment.DirectoryMovies);
                startTime = System.DateTime.Now.Millisecond;
                Android.Util.Log.Error("Encryption Started", extStore + "/" + filename);

                // This stream write the encrypted text. This stream will be wrapped by
                // another stream.
                createFile(filename, extStore);
                System.IO.FileStream fs=System.IO.File.OpenRead(extStore + "/" + filename);
                FileOutputStream fos = new FileOutputStream(extStore + "/" + filename + ".aes", false);

                // Length is 16 byte
                Cipher cipher = Cipher.GetInstance("AES/CBC/PKCS5Padding");
                byte[] raw = System.Text.Encoding.Default.GetBytes(sKey);
                SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
                IvParameterSpec iv = new IvParameterSpec(System.Text.Encoding.Default.GetBytes(ivParameter));//
                cipher.Init(CipherMode.EncryptMode, skeySpec, iv);

                // Wrap the output stream
                CipherInputStream cis = new CipherInputStream(fs, cipher);
                // Write bytes
                int b;
                byte[] d = new byte[1024 * 1024];
                while ((b = cis.Read(d)) != -1)
                {
                    fos.Write(d, 0, b);
                }
                // Flush and close streams.
                fos.Flush();
                fos.Close();
                cis.Close();
                stopTime = System.DateTime.Now.Millisecond;
                Android.Util.Log.Error("Encryption Ended", extStore + "/5mbtest/" + filename + ".aes");
                Android.Util.Log.Error("Time Elapsed", ((stopTime - startTime) / 1000.0) + "");
            }
            catch (Exception e)
            {
                Android.Util.Log.Error("lv",e.Message);
            }

        }


        private void createFile(string filename, File extStore)
        {
            File file = new File(extStore + "/" + filename + ".aes");

            if (filename.IndexOf(".") != -1)
            {
                try
                {
                    file.CreateNewFile();
                }
                catch (IOException e)
                {
                    // TODO Auto-generated catch block
                    Android.Util.Log.Error("lv",e.Message);
                }
                Android.Util.Log.Error("lv","file created");
            }
            else
            {
                file.Mkdir();
                Android.Util.Log.Error("lv","folder created");
            }

            file.Mkdirs();
        }
        public void decrypt(string filename)
        {
            try
            {

                File extStore = Environment.GetExternalStoragePublicDirectory(Environment.DirectoryMovies);
                Android.Util.Log.Error("Decryption Started", extStore + "");
                FileInputStream fis = new FileInputStream(extStore + "/" + filename + ".aes");

                createFile(filename, extStore);
                FileOutputStream fos = new FileOutputStream(extStore + "/" + "decrypted" + filename, false);
                System.IO.FileStream fs = System.IO.File.OpenWrite(extStore + "/" + "decrypted" + filename);
                // Create cipher

                Cipher cipher = Cipher.GetInstance("AES/CBC/PKCS5Padding");
                byte[] raw = System.Text.Encoding.Default.GetBytes(sKey);
                SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
                IvParameterSpec iv = new IvParameterSpec(System.Text.Encoding.Default.GetBytes(ivParameter));//
                cipher.Init(CipherMode.DecryptMode, skeySpec, iv);

                startTime = System.DateTime.Now.Millisecond;
                CipherOutputStream cos = new CipherOutputStream(fs, cipher);
                int b;
                byte[] d = new byte[1024 * 1024];
                while ((b = fis.Read(d)) != -1)
                {
                    cos.Write(d, 0, b);
                }

                stopTime = System.DateTime.Now.Millisecond;

                Android.Util.Log.Error("Decryption Ended", extStore + "/" + "decrypted" + filename);
                Android.Util.Log.Error("Time Elapsed", ((stopTime - startTime) / 1000.0) + "");

                cos.Flush();
                cos.Close();
                fis.Close();
            }
            catch (Exception e)
            {
                Android.Util.Log.Error("lv", e.Message);
            }
        }
    }
}

The video just for test, you can get the video file from another path, just a little change will be good.

About the path /storage/sdcard/Movies, I think a picture will be better to understand it

这篇关于Xamarin.android-如何更快地加密/解密图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆