Hello, this post is less than an hour after my last post, here I go again.

I recently forked out a $500 mechanical keyboard to continue my life as a coder.

File encryption and decryption, in essence, is to read the file stream, perform a series of encryption or decryption processing, and then write the byte stream after processing into the file, so as to generate encrypted or decrypted files.

First, let’s look at the structure of the library:

1. The most core part is the basic operation of our various encryption and decryption methods, such as AES encryption, DES encryption, xor encryption and so on, and of course asymmetric encryption, but not yet added.

Here is an AES helper class (AESHelper) for example, other DES, xor encryption a lot, right turn baidu.

Public class AESHelper {/** * offset variable, fixed 16 bytes */ private final static String IV_PARAMETER = "1234567812345678"; private static final String CIPHER_ALGORITHM_CBC = "AES/CBC/PKCS5Padding"; Private static final String CIPHER_ALGORITHM_ECB = "AES/ECB/PKCS5Padding"; Private static Final String CHARSET = "utF-8 "; Private static SecretKeySpec createKey(String password) {byte[] data = null; private static SecretKeySpec createKey(String password) {byte[] data = null; if (password == null) { password = ""; } StringBuffer sb = new StringBuffer(32); sb.append(password); while (sb.length() < 32) { sb.append("0"); } if (sb.length() > 32) { sb.setLength(32); } try { data = sb.toString().getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return new SecretKeySpec(data, "AES"); } /** * public static byte[] content (byte[] content, String password, boolean isSaftMode) { try { if (isSaftMode) { return encryptSaft(content, password); } else { return encryptFast(content, password); } } catch (Exception e) { e.printStackTrace(); } return null; } /** * public static byte[] decrypt(byte[] content, String password, boolean isSaftMode) { try { if (isSaftMode) { return decryptSaft(content, password); } else { return decryptFast(content, password); } } catch (Exception e) { e.printStackTrace(); } return null; } /** * encryptSaft(byte[] content, String password) { try { SecretKeySpec key = createKey(password); System.out.println(key); Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC); IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET)); cipher.init(Cipher.ENCRYPT_MODE, key, iv); byte[] result = cipher.doFinal(content); return result; } catch (Exception e) { e.printStackTrace(); } return null; } /** * public static byte[] decryptSaft(byte[] content, String password) { try { SecretKeySpec key = createKey(password); Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC); IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET)); cipher.init(Cipher.DECRYPT_MODE, key, iv); byte[] result = cipher.doFinal(content); return result; } catch (Exception e) { e.printStackTrace(); } return null; } /** * encryptFast(byte[] content, String password) { try { SecretKeySpec key = createKey(password); System.out.println(key); Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_ECB); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] result = cipher.doFinal(content); return result; } catch (Exception e) { e.printStackTrace(); } return null; } /** * public static byte[] decryptFast(byte[] content, String password) { try { SecretKeySpec key = createKey(password); Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_ECB); cipher.init(Cipher.DECRYPT_MODE, key); byte[] result = cipher.doFinal(content); return result; } catch (Exception e) { e.printStackTrace(); } return null; } /** * encryptFast(String content, String Password) public static String encryptFast(String content, String Password) {byte[] data = null; try { data = content.getBytes("UTF-8"); } catch (Exception e) { e.printStackTrace(); } data = encryptFast(data, password); String result = byte2hex(data); return result; } /** * public static String decryptFast(String Content, String password) {byte[] data = null; try { data = hex2byte(content); } catch (Exception e) { e.printStackTrace(); } data = decryptFast(data, password); if (data == null) return null; String result = null; try { result = new String(data, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return result; } public static String byte2hex(byte[] b) {public static String byte2hex(byte[] b) {  StringBuffer sb = new StringBuffer(b.length * 2); String tmp = ""; for (int n = 0; n < b.length; N++) {/ TMP/Integer into hexadecimal said = (Java. Lang. Integer. ToHexString (b [n] & 0 XFF)); if (tmp.length() == 1) { sb.append("0"); } sb.append(tmp); } return sb.toString().toUpperCase(); / / to uppercase} / * * * convert hex String into an array of bytes * * / private static byte [] hex2byte (String inputString) {if (inputString = = null | | inputString.length() < 2) { return new byte[0]; } inputString = inputString.toLowerCase(); int l = inputString.length() / 2; byte[] result = new byte[l]; for (int i = 0; i < l; ++i) { String tmp = inputString.substring(2 * i, 2 * i + 2); result[i] = (byte) (Integer.parseInt(tmp, 16) & 0xFF); } return result; }}Copy the code

2. We need to define an abstract interface for file encryption and decryption operation (IFileEncrytionControl).

Public interface IFileEncrytionControl {/** * Full parameter * * @param sourceFileTargetPath Path of the source file * @param targetFolderName Encrypted folder path * @param targetFileName encrypted file name * @param Key Key * @param startPosition Position of the file to be encrypted * @param Length Length of the part to be encrypted * @throws Exception */ void getBaseEncryptFile(String sourceFileTargetPath, String targetFolderName, String targetFileName, String key, int startPosition, int length) throws Exception; /** * Decrypt the file, Full parameter * * @param sourceFileTargetPath Source file path * @param targetFolderName Decrypted folder path * @param targetFileName decrypted file name * @param Key Key * @param startPosition Position of the file to be decrypted (consistent with the encryption position) * @param Length Length of the part to be decrypted * @throws Exception */ void getBaseDecryptFile(String sourceFileTargetPath, String targetFolderName, String targetFileName, String key, int startPosition, int length) throws Exception; /** * Encrypted file (full file encryption) ** @param sourceFileTargetPath Source file path * @param targetFolderName Encrypted folder path * @param targetFileName Encrypted file name * @param Key Key * @throws Exception */ void getEncryptFile(String sourceFileTargetPath, String targetFolderName, String targetFileName, String key) throws Exception; /** * decrypted file (full file decryption) ** @param sourceFileTargetPath Source file path * @param targetFolderName Decrypted folder path * @param targetFileName Name of the decrypted file * @param Key Key * @throws Exception */ void getDecryptFile(String sourceFileTargetPath, String targetFolderName, String targetFileName, String key) throws Exception; /** * encrypt file (automatically generate key, * * @param sourceFileTargetPath Path of the source file * @param targetFolderName Path of the encrypted folder * @param targetFileName Encrypted file name * @throws Exception. */ void getEncryptFileSelfKey(String sourceFileTargetPath, String targetFolderName, String targetFileName) throws Exception; /** * Decrypt file (read key from encrypted file) ** @param sourceFileTargetPath Source file path * @param targetFolderName Decrypted folder path * @param TargetFileName File name after decryption * @throws Exception */ void getDecryptFileSelfKey(String sourceFileTargetPath, String targetFolderName, String targetFileName) throws Exception; /** * Encrypt file (randomly generate key and encryption location information, * * @param sourceFileTargetPath Path of the source file * @param targetFolderName Path of the encrypted folder * @param targetFileName Encrypted file name * @ throws an Exception Exception * / void getEncryptFileSelfKeyAndLength (String sourceFileTargetPath, String targetFolderName, String targetFileName) throws Exception; /** * Decrypt file (obtain key and encryption location information in the file) ** @param sourceFileTargetPath Source file path * @param targetFolderName Decrypted folder path * @param TargetFileName decrypted file name * @ throws an Exception Exception * / void getDecryptFileSelfKeyAndLength (String sourceFileTargetPath, String targetFolderName, String targetFileName) throws Exception; /** * Encrypted file (automatically generated key) ** @param sourceFileTargetPath Source file path * @param targetFolderName Encrypted folder path * @param targetFileName Name of the encrypted file * @param startPosition Position of the file to be encrypted * @param Length Length of the part to be encrypted * @throws Exception */ void getEncryptFileSelfKeySomePart(String sourceFileTargetPath, String targetFolderName, String targetFileName, int startPosition, int length) throws Exception; }Copy the code

3. Define an abstract base class and implement the above abstract Operation interface (BaseEncryptionManager)

public abstract class BaseEncryptionManager implements IFileEncrytionControl {
    //加密每块的大小
    public static int FILE_BLOCK_BYTE_SIZE = 4096;

    /**
     * 加密/解密文件,全参数
     *
     * @param sourceFileTargetPath 源文件的路径
     * @param targetFolderName     加密后文件夹的路径
     * @param targetFileName       加密后的文件名
     * @param key                  的key
     * @param startPosition        开始加密的文件位置
     * @param length               需要加密部分的长度
     * @param isEncrypt            true表示加密,false表示解密
     * @throws Exception 抛出异常
     */
    protected void getBaseEncryptFileByType(String sourceFileTargetPath, String targetFolderName, String targetFileName,
                                            String key, int startPosition, int length, boolean isEncrypt) throws Exception {
        File sourceFile = new File(sourceFileTargetPath);
        if (sourceFile == null || !sourceFile.exists()) {
            throw new Exception("源文件不存在");
        }

        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;
        try {
            File targetFolder = new File(targetFolderName);
            if (!targetFolder.exists()) {
                targetFolder.mkdirs();
            }
            File targetFile = new File(targetFolderName + "/" + targetFileName);
            if (targetFile.exists()) {
                targetFile.delete();
            } else {
                targetFile.createNewFile();
            }
            inputStream = new FileInputStream(sourceFile);
            outputStream = new FileOutputStream(targetFile);
            int blockSize = 0;
            if (isEncrypt) {
                //插入文件头并获取blocksize
                blockSize = writeFileHead(outputStream);
                int[] result = writeStartPoiAndLength(startPosition, length, outputStream, sourceFile.length());
                startPosition = result[0];
                length = result[1];
                key = writeKey(key, outputStream);
                writePreDatas(startPosition, inputStream, outputStream, blockSize);
                getBaseEncrytCore(key, startPosition, length, blockSize, inputStream, outputStream, getSaftMode());
            } else {
                //获取文件头并获取blocksize
                blockSize = getFileHead(inputStream);
                startPosition = getStartPosition(startPosition, inputStream);
                length = getLength(length, inputStream);
                key = getKeyString(key, inputStream);
                writePreDatas(startPosition, inputStream, outputStream, blockSize);
                getBaseDecrytCore(key, startPosition, length, blockSize, inputStream, outputStream, getSaftMode());
            }
            writeSurplusDatas(blockSize, inputStream, outputStream);
        } catch (Exception e) {
            throw e;
        } finally {
            //释放资源
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                inputStream = null;
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                outputStream = null;
            }
        }
    }

    /**
     * 获取文件信息头
     *
     * @param inputStream
     * @return
     * @throws Exception
     */
    private int getFileHead(FileInputStream inputStream) throws Exception {
        //获取头信息
        //获取加密类型
        byte[] typeByte = new byte[1];
        inputStream.read(typeByte);
        int type = LwNetWorkTool.readInt(typeByte, 0, 1);
        if (type != getEncryptType()) {
            throw new Exception("解密类型不正确,视频类型为:" + type);
        }
        //从加密文件的前两个字节获取到加密块的大小
        byte[] blockByte = new byte[2];
        inputStream.read(blockByte);
        int blockByteSize = LwNetWorkTool.readInt(blockByte, 0, 2);
        return blockByteSize;
    }


    /**
     * 解密时获取key
     *
     * @param key
     * @param inputStream
     * @return
     * @throws Exception
     */
    private String getKeyString(String key, FileInputStream inputStream) throws Exception {
        if (StringUtil.isEmpty(key)) {
            // 如果为空,说明要去文件头获取
            byte[] passHeads = new byte[16];
            inputStream.read(passHeads);
            key = new String(passHeads, "UTF-8");
        }
        return key;
    }

    /**
     * 解密时获取长度
     *
     * @param length
     * @param inputStream
     * @return
     * @throws Exception
     */
    private int getLength(int length, FileInputStream inputStream) throws Exception {
        //去文件获取第4个字节
        byte[] lBytes = new byte[4];
        inputStream.read(lBytes);
        if (length == UNKNOW_LENGTH) {
            length = LwNetWorkTool.readInt(lBytes, 0, 4);
        }
        return length;
    }

    /**
     * 解密时获取开始位置
     *
     * @param startPosition
     * @param inputStream
     * @return
     * @throws Exception
     */
    private int getStartPosition(int startPosition, FileInputStream inputStream) throws Exception {
        //去文件获取第3位字节
        byte[] sBytes = new byte[2];
        inputStream.read(sBytes);
        if (startPosition == UNKNOW_START_POSITION) {
            startPosition = LwNetWorkTool.readInt(sBytes, 0, 2);
        }
        return startPosition;
    }

    /**
     * 写入加密内容前的数据
     *
     * @param startPosition
     * @param inputStream
     * @param outputStream
     * @param blockSize
     * @throws Exception
     */
    private void writePreDatas(int startPosition, FileInputStream inputStream, FileOutputStream outputStream, int blockSize) throws Exception {
        //如果大于0,就需要把视频文件的前面部分数据复制出来
        if (startPosition > 0) {
            byte[] beforebs = null;
            int temp = -1;
            if (startPosition < blockSize) {
                beforebs = new byte[startPosition];
                inputStream.read(beforebs);
                outputStream.write(beforebs, 0, beforebs.length);
            } else {
                int totalPage = startPosition / blockSize;
                int page = 0;
                beforebs = new byte[blockSize];
                while ((temp = inputStream.read(beforebs)) != -1) {
                    outputStream.write(beforebs, 0, temp);
                    if (page == totalPage) {
                        break;
                    }
                    page++;
                }
            }
        }
    }

    /**
     * 加密文件时候写入文件头信息
     *
     * @param outputStream
     * @return
     * @throws Exception
     */
    private int writeFileHead(FileOutputStream outputStream) throws Exception {
        //写入头信息
        int type = getEncryptType();
        byte[] typeByte = new byte[1];
        LwNetWorkTool.writeLong(typeByte, type, 0, 1);
        outputStream.write(type);
        //初始化每一块加密的大小
        int blockByteSize = FILE_BLOCK_BYTE_SIZE;
        byte[] blockByte = new byte[2];
        LwNetWorkTool.writeLong(blockByte, blockByteSize, 0, 2);
        //将每一块的加密数据大小写进加密文件的第一和第二个字节
        outputStream.write(blockByte);
        return blockByteSize;
    }

    /**
     * 加密时写入开始的位置和长度
     *
     * @param startPosition
     * @param outputStream
     * @param fileLength
     * @return
     * @throws Exception
     */
    private int[] writeStartPoiAndLength(int startPosition, int length, FileOutputStream outputStream, long fileLength) throws Exception {
        int[] result = new int[2];
        if (startPosition == UNKNOW_START_POSITION) {
            //写入文件第3个字节
            startPosition = RandomHelper.getRamdomNum(0, 64);
        }
        if (startPosition > fileLength) {
            startPosition = 0;
        }
        if (length == UNKNOW_LENGTH) {
            //写入文件第4个字节
            length = RandomHelper.getRamdomNum(16, 128);
        }
        if (length > fileLength) {
            length = (int) fileLength;
        }

        if (startPosition + length > fileLength) {
            startPosition = 0;
            length = (int) fileLength;
        }
        byte[] sByte = new byte[2];
        LwNetWorkTool.writeLong(sByte, startPosition, 0, 2);
        outputStream.write(sByte);
        byte[] lByte = new byte[4];
        LwNetWorkTool.writeLong(lByte, length, 0, 4);
        outputStream.write(lByte);
        result[0] = startPosition;
        result[1] = length;
        return result;
    }

    /**
     * 写入加密后的剩余数量
     *
     * @param blockByteSize
     * @param inputStream
     * @param outputStream
     * @throws Exception
     */
    private void writeSurplusDatas(int blockByteSize, FileInputStream inputStream, FileOutputStream outputStream) throws Exception {
        //将剩余数据写入
        byte[] bs = new byte[blockByteSize];
        int temp = -1;
        while ((temp = inputStream.read(bs)) != -1) {
            outputStream.write(bs, 0, temp);
        }
        outputStream.flush();
    }

    /**
     * 加密文件,全参数
     *
     * @param sourceFileTargetPath 源文件的路径
     * @param targetFolderName     加密后文件夹的路径
     * @param targetFileName       加密后的文件名
     * @param key                  的key
     * @param startPosition        开始加密的文件位置
     * @param length               需要加密部分的长度
     * @throws Exception 抛出异常
     */
    @Override
    public void getBaseEncryptFile(String sourceFileTargetPath, String targetFolderName, String targetFileName, String key, int startPosition, int length) throws Exception {
        getBaseEncryptFileByType(sourceFileTargetPath, targetFolderName, targetFileName, key, startPosition, length, true);
    }

    /**
     * 解密文件,全参数
     *
     * @param sourceFileTargetPath 源文件的路径
     * @param targetFolderName     解密后文件夹的路径
     * @param targetFileName       解密后的文件名
     * @param key                  的key
     * @param startPosition        开始解密的文件位置(与加密位置保持一致)
     * @param length               需要解密部分的长度
     * @throws Exception 抛出异常
     */
    @Override
    public void getBaseDecryptFile(String sourceFileTargetPath, String targetFolderName, String targetFileName, String key, int startPosition, int length) throws Exception {
        getBaseEncryptFileByType(sourceFileTargetPath, targetFolderName, targetFileName, key, startPosition, length, false);
    }

    /**
     * 加密文件(全文件加密)
     *
     * @param sourceFileTargetPath 源文件的路径
     * @param targetFolderName     加密后文件夹的路径
     * @param targetFileName       加密后的文件名
     * @param key                  的key
     * @throws Exception 抛出异常
     */
    @Override
    public void getEncryptFile(String sourceFileTargetPath, String targetFolderName, String targetFileName, String key) throws Exception {
        File sourceFile = new File(sourceFileTargetPath);
        if (sourceFile == null || !sourceFile.exists()) {
            throw new Exception("源文件不存在");
        }
        getBaseEncryptFile(sourceFileTargetPath, targetFolderName, targetFileName, key, 0, (int) sourceFile.length());
    }

    /**
     * 解密文件(全文件解密)
     *
     * @param sourceFileTargetPath 源文件的路径
     * @param targetFolderName     解密后文件夹的路径
     * @param targetFileName       解密后的文件名
     * @param key                  的key
     * @throws Exception 抛出异常
     */
    @Override
    public void getDecryptFile(String sourceFileTargetPath, String targetFolderName, String targetFileName, String key) throws Exception {
        File sourceFile = new File(sourceFileTargetPath);
        if (sourceFile == null || !sourceFile.exists()) {
            throw new Exception("源文件不存在");
        }
        getBaseDecryptFile(sourceFileTargetPath, targetFolderName, targetFileName, key, 0, UNKNOW_LENGTH);
    }

    /**
     * 加密文件(自动生成key,并写进加密文件)
     *
     * @param sourceFileTargetPath 源文件的路径
     * @param targetFolderName     加密后文件夹的路径
     * @param targetFileName       加密后的文件名
     * @throws Exception 抛出异常
     */
    @Override
    public void getEncryptFileSelfKey(String sourceFileTargetPath, String targetFolderName, String targetFileName) throws Exception {
        File sourceFile = new File(sourceFileTargetPath);
        if (sourceFile == null || !sourceFile.exists()) {
            throw new Exception("源文件不存在");
        }
        getBaseEncryptFile(sourceFileTargetPath, targetFolderName, targetFileName, "", 0, (int) sourceFile.length());
    }

    /**
     * 解密文件(从已加密的文件读取key)
     *
     * @param sourceFileTargetPath 源文件的路径
     * @param targetFolderName     解密后文件夹的路径
     * @param targetFileName       解密后的文件名
     * @throws Exception 抛出异常
     */
    @Override
    public void getDecryptFileSelfKey(String sourceFileTargetPath, String targetFolderName, String targetFileName) throws Exception {
        File sourceFile = new File(sourceFileTargetPath);
        if (sourceFile == null || !sourceFile.exists()) {
            throw new Exception("源文件不存在");
        }
        getBaseDecryptFile(sourceFileTargetPath, targetFolderName, targetFileName, "", 0, UNKNOW_LENGTH);
    }

    /**
     * 加密文件(随机生成key和加密位置的信息,并写进加密文件)
     *
     * @param sourceFileTargetPath 源文件的路径
     * @param targetFolderName     加密后文件夹的路径
     * @param targetFileName       加密后的文件名
     * @throws Exception 抛出异常
     */
    @Override
    public void getEncryptFileSelfKeyAndLength(String sourceFileTargetPath, String targetFolderName, String targetFileName) throws Exception {
        File sourceFile = new File(sourceFileTargetPath);
        if (sourceFile == null || !sourceFile.exists()) {
            throw new Exception("源文件不存在");
        }
        getBaseEncryptFile(sourceFileTargetPath, targetFolderName, targetFileName, "", UNKNOW_START_POSITION, UNKNOW_LENGTH);
    }

    /**
     * 解密文件(在文件中获取key和加密位置的信息)
     *
     * @param sourceFileTargetPath 源文件的路径
     * @param targetFolderName     解密后文件夹的路径
     * @param targetFileName       解密后的文件名
     * @throws Exception 抛出异常
     */
    @Override
    public void getDecryptFileSelfKeyAndLength(String sourceFileTargetPath, String targetFolderName, String targetFileName) throws Exception {
        File sourceFile = new File(sourceFileTargetPath);
        if (sourceFile == null || !sourceFile.exists()) {
            throw new Exception("源文件不存在");
        }
        getBaseDecryptFile(sourceFileTargetPath, targetFolderName, targetFileName, "", UNKNOW_START_POSITION, UNKNOW_LENGTH);
    }

    /**
     * 加密文件(自动生成key)
     *
     * @param sourceFileTargetPath 源文件的路径
     * @param targetFolderName     加密后文件夹的路径
     * @param targetFileName       加密后的文件名
     * @param startPosition        开始加密的文件位置
     * @param length               需要加密部分的长度
     * @throws Exception 抛出异常
     */
    @Override
    public void getEncryptFileSelfKeySomePart(String sourceFileTargetPath, String targetFolderName, String targetFileName,
                                              int startPosition, int length) throws Exception {
        getBaseEncryptFile(sourceFileTargetPath, targetFolderName, targetFileName, "", startPosition, length);
    }

//    /**
//     * 解密文件(获取加密文件内的key)
//     *
//     * @param sourceFileTargetPath 源文件的路径
//     * @param targetFolderName     解密后文件夹的路径
//     * @param targetFileName       解密后的文件名
//     * @param startPosition        开始解密的文件位置
//     * @param length               需要解密部分的长度
//     * @throws Exception 抛出异常
//     */
//    @Override
//    public void getDecryptFileSelfKeySomePart(String sourceFileTargetPath, String targetFolderName, String targetFileName,
//                                              int startPosition, int length) throws Exception {
//        getBaseDecryptFile(sourceFileTargetPath, targetFolderName, targetFileName, "", startPosition, length);
//    }

    protected abstract void getBaseEncrytCore(String key, int startPosition, int length, int blockByteSize,
                                              FileInputStream inputStream, FileOutputStream outputStream, boolean saftMode) throws Exception;

    protected abstract void getBaseDecrytCore(String key, int startPosition, int length, int blockByteSize,
                                              FileInputStream inputStream, FileOutputStream outputStream, boolean saftMode) throws Exception;

    protected abstract int getEncryptType();

    protected abstract String writeKey(String key, OutputStream outputStream) throws Exception;

    /**
     * 设置是否是安全模式,true表示加密安全优先,false表示速度优先
     *
     * @return
     */
    protected abstract boolean getSaftMode();
}
Copy the code

4. We also need to define type constants

public class BaseConstans {
    public static final int AES_ENCRYPTION = 0;
    public static final int XOR_ENCRYPTION = 1;
    public static final int DES_ENCRYPTION = 2;

    public static final int UNKNOW_START_POSITION = -1;
    public static final int UNKNOW_LENGTH = -1;
}
Copy the code

5. (core) By inheriting BaseEncryptionManager class, to achieve the core algorithm of data encryption and decryption, the following is just an example of AES encryption and decryption:

public class FileAesEncryptionUtil extends BaseEncryptionManager { public static FileAesEncryptionUtil util = null; public static FileAesEncryptionUtil getInstance() { if (util == null) { synchronized (FileAesEncryptionUtil.class) { if (util == null) { util = new FileAesEncryptionUtil(); } } } return util; } /** * Encryption core ** @param key * @param startPosition * @param length * @param inputStream * @param outputStream * @throws Exception */ @Override protected void getBaseEncrytCore(String key, int startPosition, int length, int blockByteSize, FileInputStream inputStream, FileOutputStream outputStream, Boolean saftMode) throws Exception {try {if (length < blockByteSize) {// Encrypt some data // If the length to be encrypted is smaller than the length of each block, Byte [] passDatas = new byte[length]; inputStream.read(passDatas, 0, passDatas.length); byte[] encrypt = AESHelper.encrypt(passDatas, key, saftMode); outputStream.write(encrypt); Byte [] passDatas = new byte[blockByteSize]; byte[] passDatas = new byte[blockByteSize]; int totalPage = length / passDatas.length; int page = 0; int temp = -1; byte[] encrypt = null; while ((temp = inputStream.read(passDatas)) ! = -1) { if (temp ! = passDatas.length) { byte[] lastData = new byte[temp]; System.arraycopy(passDatas, 0, lastData, 0, temp); encrypt = AESHelper.encrypt(lastData, key, saftMode); } else { encrypt = AESHelper.encrypt(passDatas, key, saftMode); } outputStream.write(encrypt); if (page == totalPage) { break; } page++; } } } catch (Exception e) { throw e; }} /** * Decrypt the core ** @param key * @param startPosition * @param length * @param inputStream * @param outputStream * @throws Exception */ @Override protected void getBaseDecrytCore(String key, int startPosition, int length, int blockByteSize, FileInputStream inputStream, FileOutputStream outputStream, Boolean saftMode) throws Exception {try {//length Must be a multiple of 16 if (length % 16! = 0) { int count = (length / 16) + 1; length = count * 16; } else { length = length + 16; } if (length < blockByteSize) {// Decrypt part of data // Decrypt byte[] passDatas = new byte[length]; inputStream.read(passDatas, 0, passDatas.length); byte[] decrypt = AESHelper.decrypt(passDatas, key, saftMode); outputStream.write(decrypt); Byte [] passDatas = new byte[blockByteSize +16]; byte[] passDatas = new byte[blockByteSize +16]; byte[] passDatas = new byte[blockByteSize +16]; int totalPage = length / passDatas.length; int page = 0; int temp = -1; byte[] decrypt = null; while ((temp = inputStream.read(passDatas)) ! = -1) { if (temp ! = passDatas.length) { byte[] lastData = new byte[temp]; System.arraycopy(passDatas, 0, lastData, 0, temp); decrypt = AESHelper.decrypt(lastData, key, saftMode); } else { decrypt = AESHelper.decrypt(passDatas, key, saftMode); } outputStream.write(decrypt); if (page == totalPage) { break; } page++; } } } catch (Exception e) { throw e; } } @Override protected int getEncryptType() { return AES_ENCRYPTION; } @Override protected String writeKey(String key, OutputStream OutputStream) throws Exception {if (stringutil. isEmpty(key)) {// if it isEmpty, Explain to randomly generated and written in the file header key = RandomHelper. GetNumSmallCharRandom (16); byte[] passHeads = key.getBytes(); outputStream.write(passHeads, 0, passHeads.length); } return key; } @Override protected boolean getSaftMode() { return EncryptionModeManager.IS_SAFT_ENCRYPT_MODE; }}Copy the code

The library can write keys to video files or pass them in externally; You can encrypt and decrypt all the data of the file, or only encrypt and decrypt part of the data, saving time.

After writing the library, I realized that the code really needs to be optimized bit by bit. When the library was originally written, all the methods and functions were written in a FileAesEncryptionUtil class, making it difficult to extend other encryption methods. Then I have to figure out how to separate out the operation that has the same encryption method and form an interface that implements that operation each time I add an encryption method. After this operation, the library’s extensibility has improved. Just when I think I can call it a day, the actual situation is met with other problems, when I joined the DES encryption and xor encryption, found that a lot of methods of these classes are the same steps, reusability is still not up to. No way, I can only continue to pull out the same part, put in a base class, inherit the base class subclass only need to achieve data encryption and data decryption part is enough, other file processing, stream processing, file header processing, are handed to the base class method to do. This way, the extension will be more convenient, and it will be faster to insert more encryption methods. In addition, the file encryption and decryption processing also score slice read, otherwise all byte array read out at one time, so it will cause android classic problem OOM.

Code shuttles can be fun for a while, but the value of the code will increase only after various integration and refactoring.