Encryption and decryption of Android files

The process and principle of file encryption and decryption

1. Encryption method: When storing a file, intercept the byte array of the file from the input stream and encrypt the byte array. As for the encryption method and algorithm, it can be determined according to the needs, and then write the encrypted byte array. into the file, and finally generate the encrypted file;

2. Decryption method: the same as the encryption method, except that the byte data is decrypted, and finally a plaintext file is generated;

3. Encryption algorithm: The android system itself introduces the Cipher class of the javax package, which provides a variety of general encryption methods, such as AES symmetric encryption, etc. There is a CipherUtil tool class in this program, which contains some simple The method of using Cipher for AES encryption and decryption; of course, it is best to learn the use of the Cipher class;

4. Notes:

        a、如何判断一个文件是加密后的文件,最简单的方法就是对加密后的文件统一增加一个后缀名,
        然后在解密之后将这个后缀名去除,还原回原有文件格式;

        如:密文文件的统一后缀名为“.cipher”,明文文件名为"测试.txt",加密后的密文文件应该为“测试.txt.cipher”;

        b、加密文件时还有一个重要的注意事项,就是加密后的密文和明文的长度是否相同,
        如果文件时一次读取出所有字节数组进行加密的话不用担心这个问题,
        但是当对文件分次读取加密或分段加密的话,就不得不考虑这个问题了,最方便的方法就是保证明文和加密后的密文长度相同;
        如果长度不同,由于是分段加密的,密文是由一段一段子密文拼接成的,
        解密时会找不到每段子密文,因为不知道每段子密文的长度是多少;

main code

/**Customize a simple file encryption and decryption tool
 * Created by zhangshuo on 2016/6/28.
 */
public class CustomFileCipherUtil {

    /**
     * The suffix of the encrypted file
     */
    public static final String CIPHER_TEXT_SUFFIX = ".cipher";

    /**
     * Encryption and decryption calculations are performed in units of 32K bytes during encryption and decryption
     */
    private static final int CIPHER_BUFFER_LENGHT = 32 * 1024;

    /**
     * Encryption, here is mainly to demonstrate the principle of encryption, no actual encryption algorithm is used
     *
     * @param filePath absolute path of plaintext file
     * @return
     */
    public static boolean encrypt(String filePath, CipherListener listener) {
        try {
            long startTime = System.currentTimeMillis();
            File f = new File(filePath);
            RandomAccessFile raf = new RandomAccessFile(f, "rw");
            long totalLenght = raf.length();
            FileChannel channel = raf.getChannel();

            long multiples = totalLenght / CIPHER_BUFFER_LENGHT;
            long remainder = totalLenght % CIPHER_BUFFER_LENGHT;

            MappedByteBuffer buffer = null;
            byte tmp;
            byte rawByte;

            // first encrypt the divisible part
            for(int i = 0; i < multiples; i++){
                buffer = channel.map(
                        FileChannel.MapMode.READ_WRITE, i * CIPHER_BUFFER_LENGHT, (i + 1) * CIPHER_BUFFER_LENGHT);

                //The encryption method here is very simple, just a simple XOR calculation
                for (int j = 0; j < CIPHER_BUFFER_LENGHT; ++j) {
                    rawByte = buffer.get(j);
                    tmp = (byte) (rawByte ^ j);
                    buffer.put(j, tmp);

                    if(null != listener){
                        listener.onProgress(i * CIPHER_BUFFER_LENGHT + j, totalLenght);
                    }
                }
                buffer.force();
                buffer.clear();
            }

            // encrypt the remainder
            buffer = channel.map(
                    FileChannel.MapMode.READ_WRITE, multiples * CIPHER_BUFFER_LENGHT, multiples * CIPHER_BUFFER_LENGHT + remainder);

            for (int j = 0; j < remainder; ++j) {
                rawByte = buffer.get(j);
                tmp = (byte) (rawByte ^ j);
                buffer.put(j, tmp);

                if(null != listener){
                    listener.onProgress(multiples * CIPHER_BUFFER_LENGHT + j, totalLenght);
                }
            }
            buffer.force();
            buffer.clear();

            channel.close();
            raf.close();

            //Rename the encrypted file and add the .cipher suffix
//            f.renameTo(new File(f.getPath() + CIPHER_TEXT_SUFFIX));
            Log.d("Encryption time: ", (System.currentTimeMillis() - startTime) /1000 + "s");
            return true;
        } catch (Exception e) {
            e.printStackTrace ();
            return false;
        }
    }


    /**
     * Decryption, here is mainly to demonstrate the principle of encryption, no actual encryption algorithm is used
     *
     * @param filePath The absolute path of the ciphertext file, the file needs to end with .cipher to think that the ciphertext can actually be decrypted
     * @return
     */
    public static boolean decrypt(String filePath, CipherListener listener) {
        try {
            long startTime = System.currentTimeMillis();
            File f = new File(filePath);
//            if(!f.getPath().toLowerCase().endsWith(CIPHER_TEXT_SUFFIX)){
// //The suffix is ​​different, it is considered as undecipherable ciphertext
//                return false;
//            }

            RandomAccessFile raf = new RandomAccessFile(f, "rw");
            long totalLenght = raf.length();
            FileChannel channel = raf.getChannel();

            long multiples = totalLenght / CIPHER_BUFFER_LENGHT;
            long remainder = totalLenght % CIPHER_BUFFER_LENGHT;

            MappedByteBuffer buffer = null;
            byte tmp;
            byte rawByte;

            //decrypt the divisible part first
            for(int i = 0; i < multiples; i++){
                buffer = channel.map(
                        FileChannel.MapMode.READ_WRITE, i * CIPHER_BUFFER_LENGHT, (i + 1) * CIPHER_BUFFER_LENGHT);

                //The decryption method here is very simple, just a simple XOR calculation
                for (int j = 0; j < CIPHER_BUFFER_LENGHT; ++j) {
                    rawByte = buffer.get(j);
                    tmp = (byte) (rawByte ^ j);
                    buffer.put(j, tmp);

                    if(null != listener){
                        listener.onProgress(i * CIPHER_BUFFER_LENGHT + j, totalLenght);
                    }
                }
                buffer.force();
                buffer.clear();
            }

            // decrypt the remainder
            buffer = channel.map(
                    FileChannel.MapMode.READ_WRITE, multiples * CIPHER_BUFFER_LENGHT, multiples * CIPHER_BUFFER_LENGHT + remainder);

            for (int j = 0; j < remainder; ++j) {
                rawByte = buffer.get(j);
                tmp = (byte) (rawByte ^ j);
                buffer.put(j, tmp);

                if(null != listener){
                    listener.onProgress(multiples * CIPHER_BUFFER_LENGHT + j, totalLenght);
                }
            }
            buffer.force();
            buffer.clear();

            channel.close();
            raf.close();

            //Rename the encrypted file and add the .cipher suffix
//            f.renameTo(new File(f.getPath().substring(f.getPath().toLowerCase().indexOf(CIPHER_TEXT_SUFFIX))));

            Log.d("Decryption time: ", (System.currentTimeMillis() - startTime) / 1000 + "s");
            return true;
        } catch (Exception e) {
            e.printStackTrace ();
            return false;
        }
    }

    /**
     * Listener for encryption and decryption progress
     */
    public interface CipherListener{
        void onProgress(long current, long total);
    }
}


screenshot

image1


Demo download address:

https://github.com/ZhangSir/TestCipher

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325901589&siteId=291194637