Android 采用AES加解密大文件,以及Android使用AES算法加解密大文件时OOM

前言

Android 由于机制问题,到时加载大文件时oom.

项目中有需要对大文件进行AES加密,于是他来了。

在activity 调用。AESCIpher()方法如下图

该方法四个字段

                参数一  1.代表加密,2代表解密

                参数二  需要加解密文件的路径

                参数三 得到加解密文件的路径

                参数四 生成秘钥的源文件

//Activity调用
new Thread(){
        @Override
        public void run() {
            super.run();
            //AESCipher(参数1,参数二,参数三,参数四);参数一1代表加密,2代表解密,  参数二 需要加解密的文件路径,参数三得到加解密的文件的路径,参数4数生成秘钥的原始文件;参考下面getRawKey可以把我注释掉的代码运行以下
            AESCipher(1, SDcardPath + "/eBook/成功经验/航空兵防空部队战法1/三国.mp4",
                    SDcardPath + "/eBook/成功经验/航空兵防空部队战法1/三国加密.mp4","asdasdas");

            AESCipher(2, SDcardPath + "/eBook/成功经验/航空兵防空部队战法1/三国加密.mp4",
                    SDcardPath + "/eBook/成功经验/航空兵防空部队战法1/三国解密.mp4","asdasdas");
        }
    }.start();

加密类

具体的加密方法

    

//具体加密方法
    public final String TAG = "AES";
    public boolean AESCipher(int cipherMode, String sourceFilePath,
                             String targetFilePath, String seed) {
        boolean result = false;
        FileChannel sourceFC = null;
        FileChannel targetFC = null;

        try {

            if (cipherMode != Cipher.ENCRYPT_MODE
                    && cipherMode != Cipher.DECRYPT_MODE) {
                Log.d(TAG,
                        "Operation mode error, should be encrypt or decrypt!");
                return false;
            }

            Cipher mCipher = Cipher.getInstance("AES/CFB/NoPadding");

            byte[] rawkey = new byte[0];
            try {
                rawkey = getRawKey(seed.getBytes());
            } catch (Exception e) {
                e.printStackTrace();
            }
            File sourceFile = new File(sourceFilePath);
            File targetFile = new File(targetFilePath);

            sourceFC = new RandomAccessFile(sourceFile, "r").getChannel();
            targetFC = new RandomAccessFile(targetFile, "rw").getChannel();

            SecretKeySpec secretKey = new SecretKeySpec(rawkey, "AES");

            mCipher.init(cipherMode, secretKey, new IvParameterSpec(
                    new byte[mCipher.getBlockSize()]));

            ByteBuffer byteData = ByteBuffer.allocate(1024);
            while (sourceFC.read(byteData) != -1) {
                // 通过通道读写交叉进行。
                // 将缓冲区准备为数据传出状态
                byteData.flip();

                byte[] byteList = new byte[byteData.remaining()];
                byteData.get(byteList, 0, byteList.length);
//此处,若不使用数组加密解密会失败,因为当byteData达不到1024个时,加密方式不同对空白字节的处理也不相同,从而导致成功与失败。
                byte[] bytes = mCipher.doFinal(byteList);
                targetFC.write(ByteBuffer.wrap(bytes));
                byteData.clear();
            }

            result = true;
        } catch (IOException | NoSuchAlgorithmException
                | InvalidKeyException
                | InvalidAlgorithmParameterException
                | IllegalBlockSizeException | BadPaddingException
                | NoSuchPaddingException e) {
            Log.d(TAG, e.getMessage());

        } finally {
            try {
                if (sourceFC != null) {
                    sourceFC.close();
                }
                if (targetFC != null) {
                    targetFC.close();
                }
            } catch (IOException e) {
                Log.d(TAG, e.getMessage());
            }
        }

        return result;
    }

    /**
     * 加密后的字符串
     *
     * @param seed
     * @return
     */
    public String encrypt(String seed, String source) {
        // Log.d(TAG, "加密前的seed=" + seed + ",内容为:" + clearText);
        byte[] result = null;
        try {
            byte[] rawkey = getRawKey(seed.getBytes());
            result = encrypt(rawkey, source.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }
        String content = toHex(result);
        return content;

    }

    /**
     * 解密后的字符串
     *
     * @param seed
     * @param encrypted
     * @return
     */
    public String decrypt(String seed, String encrypted) {
        byte[] rawKey;
        try {
            rawKey = getRawKey(seed.getBytes());
            byte[] enc = toByte(encrypted);
            byte[] result = decrypt(rawKey, enc);
            String coentn = new String(result);
            return coentn;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 对密钥进行处理
     */
    public static byte[] getRawKey(byte[] seed) throws Exception {
        byte[] rawKey = InsecureSHA1PRNGKeyDerivator.deriveInsecureKey(seed, 32);
//        writeFile(rawKey,Environment.getExternalStorageDirectory().getPath() + "/AESKEY.txt");
        return rawKey;
    }

    /**
     * 结合密钥生成加密后的密文
     *
     * @param raw
     * @param input
     * @return
     * @throws Exception
     */
    private byte[] encrypt(byte[] raw, byte[] input) throws Exception {
        // 根据上一步生成的密匙指定一个密匙
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        // Cipher cipher = Cipher.getInstance("AES");
        // 加密算法,加密模式和填充方式三部分或指定加密算
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        // 初始化模式为加密模式,并指定密匙
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(
                new byte[cipher.getBlockSize()]));
        byte[] encrypted = cipher.doFinal(input);
        return encrypted;
    }

    /**
     * 根据密钥解密已经加密的数据
     *
     * @param raw
     * @param encrypted
     * @return
     * @throws Exception
     */
    private byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
       
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值