使用AES进行文件加密算法

2022-06-19 13:59:16 浏览数 (3)

使用AES进行文件加密算法

前言:最近想对手机上一些文件进行加密隐藏,想自己基于jvm平台写一个(kotlin/java)但是网上的加密算法都是不公开的,所以自己利用AES的算法整出了一个文件加密解密的工具 注意:因为我电脑上的JDK是12 ,所以如果移植到安卓上有出现报错,是正常现象,只需要修改 AESEncoder 文件就好了

FileEncoder.kt

代码语言:text复制
import java.io.Closeable
import java.io.File
import java.io.RandomAccessFile
import java.lang.StringBuilder
/** * 文件加密 * 注意!!千万不可以使用多线程来同时加密/解密多个文件 */
class FileEncoder(passwd: String,val debug: Boolean = true, bufferSize: Int = (1024 * 1024 * 1)) : Closeable
{    
    private val aesEncoder = AESEncoder(passwd)    
    private val buffer = ByteArray(bufferSize)    
    private val spliteStr = "|"    
    /**     * 加密算法     * [msgLen | encode_file | msg]     */    
    fun encode(src: File, e_file: File, process: (process: Float) -> Unit)    
    {        
        val srcLen = src.length().toFloat()        
        val fis = src.inputStream()        
        val accessFile = RandomAccessFile(e_file, "rw")        
        // 这里在文件顶部写入8位的占位符        
        var msgLen = 0L        
        val headBytes = long2Bytes(msgLen)        
        accessFile.write(headBytes)        
        log("写入头部信息")        
        val msgBuilder = StringBuilder()        
        var readLen = fis.read(buffer)        
        var readCount = 0L        
        while (readLen > 0)        
        {            
            readCount  = readLen            
            val encodeArray = aesEncoder.encode(buffer, readLen)            
            msgBuilder.append(encodeArray.size).append(spliteStr)            
            accessFile.write(encodeArray)            
            process.invoke(readCount / srcLen)            
            readLen = fis.read(buffer)        
        }        
        val msg = msgBuilder.toString()        
        msgBuilder.setLength(0)        
        log(msg)        
        // 将尾部信息转换成字节数组        
        val msgByteArry = msg.toByteArray()        
        // 将尾部信息字节数组,加密        
        val msgEncodeByteArray = aesEncoder.encode(msgByteArry, msgByteArry.size)        
        // 写入加密尾部信息        
        accessFile.write(msgEncodeByteArray)        
        log("写入加密尾部信息")        
        // 测量出加密后的信息长度是多少        
        msgLen = msgEncodeByteArray.size.toLong()        
        log("新的长度:$msgLen")        
        // 将光标移动到文件头,复写信息        
        accessFile.seek(0)        
        // 重新将长度写入进去        
        accessFile.write(long2Bytes(msgLen))        
        fis.close()        
        accessFile.close()    
    }    
    /**     * 解密算法     */    
    fun decode(src: File, d_file: File, process: (process: Float) -> Unit)    
    {        
        val buffer: ByteArray        
        val raf = RandomAccessFile(src, "r")        
        val fos = d_file.outputStream()        
        val headBytes = ByteArray(8)        
        val headLen = raf.read(headBytes)        
        if (headLen != 8)        
        {            
            raf.close()            
            fos.close()            
            return        
        }        
        val msgLen = bytes2Long(headBytes)        
        log("解密:$msgLen")        
        val srcLen = src.length()        
        val msgByteArray = ByteArray(msgLen.toInt())        
        // 将光标移动到尾部,读取信息        
        raf.seek(srcLen - msgLen)        
        val readMsgLen = raf.read(msgByteArray)        
        log("已读取信息长度:$readMsgLen")        
        val decodeMsgArray = aesEncoder.decode(msgByteArray, msgByteArray.size)        
        val decodeMsg = String(decodeMsgArray)        
        log(decodeMsg)        
        val msgs = decodeMsg.split(spliteStr).dropLastWhile { it.isEmpty() }        
        val msgLong = msgs.map { it.toLong() }        
        val maxBufferSize = msgLong.max() ?: 0        
        buffer = ByteArray(maxBufferSize.toInt())        
        log(msgLong)        
        // 将光标回到读取完头部信息的位置        
        raf.seek(8)        
        msgLong.forEachIndexed { index, len ->            
                raf.read(buffer, 0, len.toInt())            
                val encodeArray = aesEncoder.decode(buffer, len.toInt())            
                fos.write(encodeArray)            
                process.invoke(index.toFloat() / msgLong.size)        
        }        
        process.invoke(1f)        
        fos.flush()        
        fos.close()    
    }    
    /**     * 长整型转换成字节数组     */    
    private fun long2Bytes(num: Long): ByteArray    
    {        
        val byteNum = ByteArray(8)        
        for (ix in 0..7)        
        {            
            val offset = 64 - (ix   1) * 8            
            byteNum[ix] = (num shr offset and 0xff).toByte()        
        }        
        return byteNum    
    }    
    /**     * 字节数组转换成长整型     */    
    private fun bytes2Long(byteNum: ByteArray): Long    
    {        
        var num: Long = 0        
        for (ix in 0..7)        
        {            
            num = num shl 8            
            num = num or (byteNum[ix].toInt() and 0xff).toLong()        
        }        
        return num    
    }    
    private inline fun log(msg: Any?)    
    {        
        if (debug)        
        {            
            println(msg)        
        }    
    }    
    override fun close()    
    {        
        aesEncoder.close()    
    }
}

AESEncoder.kt

代码语言:javascript复制
import java.io.Closeable
import java.security.SecureRandom
import java.util.*
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.spec.SecretKeySpec
/* * AES对称加密和解密 */
class AESEncoder(encodeRules: String) : Closeable
{    
    private val encoder = Base64.getEncoder()   
    private val decoder = Base64.getDecoder()    
    private var encodeCipher: Cipher    
    private var decoderCipher: Cipher    
    private val bufferHolder = LinkedHashMap<Int, ByteArray>()    
    init    
    {        
        //1.构造密钥生成器,指定为AES算法,不区分大小写        
        val keygen = KeyGenerator.getInstance("AES")        
        //2.根据ecnodeRules规则初始化密钥生成器        
        //生成一个128位的随机源,根据传入的字节数组        
        keygen.init(128, SecureRandom(encodeRules.toByteArray()))        
        //3.产生原始对称密钥        
        val original_key = keygen.generateKey()        
        //4.获得原始对称密钥的字节数组        
        val raw = original_key.encoded        
        //5.根据字节数组生成AES密钥        
        val key = SecretKeySpec(raw, "AES")        
        //6.根据指定算法AES自成密码器        
        encodeCipher = Cipher.getInstance("AES")        
        decoderCipher = Cipher.getInstance("AES")       
        //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY        
        encodeCipher.init(Cipher.ENCRYPT_MODE, key)        
        //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY        
        decoderCipher.init(Cipher.DECRYPT_MODE, key)    
    }    
    /*     * 加密     * 1.构造密钥生成器     * 2.根据ecnodeRules规则初始化密钥生成器     * 3.产生密钥     * 4.创建和初始化密码器     * 5.内容加密     * 6.返回字符串     */    
    fun encode(content: ByteArray, len: Int): ByteArray   
    {        
        var buffer = bufferHolder[len]        
        if (buffer == null)        
        {            
            buffer = ByteArray(len)            
            bufferHolder[len] = buffer        
        }        
        System.arraycopy(content, 0, buffer, 0, len)        
        //8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码        
        val byte_encode = buffer        
        //9.根据密码器的初始化方式--加密:将数据加密        
        val byte_AES = encodeCipher.doFinal(byte_encode)        
        //10.将加密后的数据转换为字符串        
        //这里用Base64Encoder中会找不到包        
        //解决办法:        //在项目的Build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了。        
        //11.将字符串返回        
        return encoder.encode(byte_AES)    
    }    
    /*     * 解密     * 解密过程:     * 1.同加密1-4步     * 2.将加密后的字符串反纺成byte[]数组     * 3.将加密内容解密     */    
    fun decode(content: ByteArray, len: Int): ByteArray    
    {        
        var buffer = bufferHolder[len]        
        if (buffer == null)        
        {            
            buffer = ByteArray(len)            
            bufferHolder[len] = buffer        
        }        
        System.arraycopy(content, 0, buffer, 0, len)        
        //8.将加密并编码后的内容解码成字节数组        
        val byte_content = decoder.decode(buffer)        
        /*         * 解密         */        
        val byte_decode = decoderCipher.doFinal(byte_content)        
        return byte_decode    
    }    
    override fun close()    
    {        
        bufferHolder.clear()    
    }
}

效果

右边是加密后的文件,左边是解密后的文件

老群被封, 新Q群709287944

0 人点赞