常见的加解密算法【MD5, AES, RSA等】

目录

1. 摘要算法

MD5的算法过程

SHA1算法

MD5与SHA1算法的比较

2. 对称加密

AES加密算法

DES加密算法

3. 非对称加密

RSA

DSA


1. 摘要算法

常见的摘要算法主要有两种,MD5和SHA1。

摘要算法并不是一种加密算法,因为不可逆,无法从密文还原出明文。

摘要算法主要用途有

  • 消息完整性验证:发送消息时,将发送数据与MD5值一起发送,然后可以从MD5值来验证接收到的消息是否完整。常见的有下载文件等场景,服务端提供一个文件的下载地址和文件的MD5值,客户端再下载完成后验证文件的MD5,如果与服务端的值不同,说明下载出问题了,需要重新下载。
  • 安全访问认证:如数据库存储登录密码的MD5值,这样就可以保证即使管理员也无法查看到常用密码;
  • 数字签名:常见的场景有对接口参数进行签名,来实现服务端对客户端的可靠性验证。客户端和服务端各自持有一个秘钥key,网络接口请求时,通过对时间戳timestamp+接口参数+秘钥key进行MD5计算,然后将MD5值作为参数传给服务端,服务端通过相同的加密算法来验证MD5值是否相同,通过这样来验证客户端的可信性,有效防止网络爬虫;

MD5算法

MD5输出一个32位长度的16进制字符串。Kotlin下使用方法如下

    fun getMd5(str: String): String {
        var md: MessageDigest? = null
        try {
            md = MessageDigest.getInstance("MD5")
            md.update(str.toByteArray())
            return BigInteger(1, md!!.digest()).toString(16)
        } catch (e: NoSuchAlgorithmException) {
            e.printStackTrace()
        }
        return ""
    }

我们验证下他的执行效率, 代码如下:

class LkUtilsTest {
    @Test
    fun testMd5() {
        val begin = System.currentTimeMillis()
        val result = LKUtil.getMd5("123456789012345678990")
        val end = System.currentTimeMillis()
        println("cost:" + (end - begin) + ":" + result)
    }
}

结果如下

cost:28:7f3ee0d5fd4769b75c34dcc56fc271bf

可以看到用了28ms

MD5的算法过程

查考文章 https://blog.csdn.net/u012611878/article/details/54000607

MD5的算法过程可以简要描述为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位的子分组,又经过一系列的处理后,算法的输出由是个32位分组组成,将这是个32位分组级联后将产生一个128位散列值。

  • 第一步、填充。如果输入信息长度(bit)对512求余的结果不等于448,就需要填充使得对512求余的结果等于448,就需要填充使得对512求余的结果等于448。填充的方法是填充一个1和n个0(注意这里都是bit级别的1和0),填充完成后,信息的长度就是N*512+448(bit);
  • 第二步、记录信息的长度,用64位来存储填充前信息的长度。这64位加在第一步结果的后面,这样的信息长度就变成N*512+448+64=(N+1)*512位。
  • 第三步、装入标准的幻数(四个整数),标准的幻数是A=OX67452301L,B=OXEFCDAB89L,C=OX98BADCFEL,D=OX10325476L。至于为什么是这四个数,我暂时没有搞清楚。
  • 第四步、四轮循环运算:循环的次数是分组的个数(N+1),运算的规则如下
  • 第4.1 步、每一个分组(512个字节)细分为16个小组,每个小组64位(8个字节)
  • 第4.2 步、先认识四个线性函数,定义如下

F(X,Y,Z)=(X&Y)|((~X)&Z)

G(X,Y,Z)=(X&Z)|(Y&(~Z))

H(X,Y,Z)=X^Y^Z

I(X,Y,Z)=Y^(X|(~Z))

  • 第4.3步、设Mj表示第j个子分组(从0到16),有以下4个函数

FF(a,b,c,d,Mj,s,ti)表示a=b+((a+F(b,c,d)+Mj+ti)<<<s)

GG(a,b,c,d,Mj,s,ti)表示a=b+((a+G(b,c,d)+Mj+ti)<<<s)

HH(a,b,c,d,Mj,s,ti)表示a=b+((a+H(b,c,d)+Mj+ti)<<<s)

II(a,b,c,d,Mj,s,ti)表示a=b+((a+I(b,c,d)+Mj+ti)<<<s)

  • 第4.4步,四轮运算
 第一轮
a=FF(a,b,c,d,M0,7,0xd76aa478)
b=FF(d,a,b,c,M1,12,0xe8c7b756)
c=FF(c,d,a,b,M2,17,0x242070db)
d=FF(b,c,d,a,M3,22,0xc1bdceee)
a=FF(a,b,c,d,M4,7,0xf57c0faf)
b=FF(d,a,b,c,M5,12,0x4787c62a)
c=FF(c,d,a,b,M6,17,0xa8304613)
d=FF(b,c,d,a,M7,22,0xfd469501)
a=FF(a,b,c,d,M8,7,0x698098d8)
b=FF(d,a,b,c,M9,12,0x8b44f7af)
c=FF(c,d,a,b,M10,17,0xffff5bb1)
d=FF(b,c,d,a,M11,22,0x895cd7be)
a=FF(a,b,c,d,M12,7,0x6b901122)
b=FF(d,a,b,c,M13,12,0xfd987193)
c=FF(c,d,a,b,M14,17,0xa679438e)
d=FF(b,c,d,a,M15,22,0x49b40821)

第二轮
a=GG(a,b,c,d,M1,5,0xf61e2562)
b=GG(d,a,b,c,M6,9,0xc040b340)
c=GG(c,d,a,b,M11,14,0x265e5a51)
d=GG(b,c,d,a,M0,20,0xe9b6c7aa)
a=GG(a,b,c,d,M5,5,0xd62f105d)
b=GG(d,a,b,c,M10,9,0x02441453)
c=GG(c,d,a,b,M15,14,0xd8a1e681)
d=GG(b,c,d,a,M4,20,0xe7d3fbc8)
a=GG(a,b,c,d,M9,5,0x21e1cde6)
b=GG(d,a,b,c,M14,9,0xc33707d6)
c=GG(c,d,a,b,M3,14,0xf4d50d87)
d=GG(b,c,d,a,M8,20,0x455a14ed)
a=GG(a,b,c,d,M13,5,0xa9e3e905)
b=GG(d,a,b,c,M2,9,0xfcefa3f8)
c=GG(c,d,a,b,M7,14,0x676f02d9)
d=GG(b,c,d,a,M12,20,0x8d2a4c8a)

第三轮
a=HH(a,b,c,d,M5,4,0xfffa3942)
b=HH(d,a,b,c,M8,11,0x8771f681)
c=HH(c,d,a,b,M11,16,0x6d9d6122)
d=HH(b,c,d,a,M14,23,0xfde5380c)
a=HH(a,b,c,d,M1,4,0xa4beea44)
b=HH(d,a,b,c,M4,11,0x4bdecfa9)
c=HH(c,d,a,b,M7,16,0xf6bb4b60)
d=HH(b,c,d,a,M10,23,0xbebfbc70)
a=HH(a,b,c,d,M13,4,0x289b7ec6)
b=HH(d,a,b,c,M0,11,0xeaa127fa)
c=HH(c,d,a,b,M3,16,0xd4ef3085)
d=HH(b,c,d,a,M6,23,0x04881d05)
a=HH(a,b,c,d,M9,4,0xd9d4d039)
b=HH(d,a,b,c,M12,11,0xe6db99e5)
c=HH(c,d,a,b,M15,16,0x1fa27cf8)
d=HH(b,c,d,a,M2,23,0xc4ac5665)

第四轮
a=II(a,b,c,d,M0,6,0xf4292244)
b=II(d,a,b,c,M7,10,0x432aff97)
c=II(c,d,a,b,M14,15,0xab9423a7)
d=II(b,c,d,a,M5,21,0xfc93a039)
a=II(a,b,c,d,M12,6,0x655b59c3)
b=II(d,a,b,c,M3,10,0x8f0ccc92)
c=II(c,d,a,b,M10,15,0xffeff47d)
d=II(b,c,d,a,M1,21,0x85845dd1)
a=II(a,b,c,d,M8,6,0x6fa87e4f)
b=II(d,a,b,c,M15,10,0xfe2ce6e0)
c=II(c,d,a,b,M6,15,0xa3014314)
d=II(b,c,d,a,M13,21,0x4e0811a1)
a=II(a,b,c,d,M4,6,0xf7537e82)
b=II(d,a,b,c,M11,10,0xbd3af235)
c=II(c,d,a,b,M2,15,0x2ad7d2bb)
d=II(b,c,d,a,M9,21,0xeb86d391)
  • 第4.5步 将每轮循环的结果a,b,c,d分别累加,然后进行下一轮循环

我们手撸一下MD5的过程(注:我算出来的结果与官方的结果不一样,我也不知道哪里错了,反正就是这个意思,累死了,懒得看了)

package com.plbear.lxc.utils

import kotlin.experimental.and


class Md5 {
    companion object {
        val hex = charArrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F')

        //标准的幻数
        const val A = 0x67452301L
        const val B = 0xefcdab89L
        const val C = 0x98badcfeL
        const val D = 0x10325476L

        //下面这些S11-S44实际是一个4*4的矩阵,在四轮循环运算中用到
        const val S11 = 7
        const val S12 = 12
        const val S13 = 17
        const val S14 = 22

        const val S21 = 5
        const val S22 = 9
        const val S23 = 14
        const val S24 = 20

        const val S31 = 4
        const val S32 = 11
        const val S33 = 16
        const val S34 = 23

        const val S41 = 6
        const val S42 = 10
        const val S43 = 15
        const val S44 = 21

        private fun F(x: Long, y: Long, z: Long): Long {
            return (x and y) or (x.inv() and z)
        }

        private fun G(x: Long, y: Long, z: Long): Long {
            return (x and z) or (y and z.inv())
        }

        private fun H(x: Long, y: Long, z: Long): Long {
            return x xor y xor z
        }

        private fun I(x: Long, y: Long, z: Long): Long {
            return y xor (x xor z.inv())
        }

        private fun FF(tmpA: Long, b: Long, c: Long, d: Long, x: Long, s: Int, ac: Long): Long {
            var a = tmpA
            a += (F(b, c, d) and 0xFFFFFFFFL) + x + ac
            a = ((a and 0xFFFFFFFFL) shl s.toInt()) or ((a and 0xFFFFFFFFL) ushr (32 - s.toInt()))
            a += b
            return a and 0xFFFFFFFFL
        }

        private fun GG(tmpA: Long, b: Long, c: Long, d: Long, x: Long, s: Int, ac: Long): Long {
            var a = tmpA
            a += (G(b, c, d) and 0xFFFFFFFFL) + x + ac
            a = ((a and 0xFFFFFFFFL) shl s.toInt()) or ((a and 0xFFFFFFFFL) ushr (32 - s.toInt()))
            a += b
            return a and 0xFFFFFFFFL
        }

        private fun HH(tmpA: Long, b: Long, c: Long, d: Long, x: Long, s: Int, ac: Long): Long {
            var a = tmpA
            a += (H(b, c, d) and 0xFFFFFFFFL) + x + ac
            a = ((a and 0xFFFFFFFFL) shl s.toInt()) or ((a and 0xFFFFFFFFL) ushr (32 - s.toInt()))
            a += b
            return a and 0xFFFFFFFF
        }

        private fun II(tmpA: Long, b: Long, c: Long, d: Long, x: Long, s: Int, ac: Long): Long {
            var a = tmpA
            a += (I(b, c, d) and 0xFFFFFFFFL) + x + ac
            a = ((a and 0xFFFFFFFFL) shl s.toInt()) or ((a and 0xFFFFFFFFL) ushr (32 - s.toInt()))
            a += b
            return a and 0xFFFFFFFF
        }
    }

    val result = arrayOf(A, B, C, D)

    fun md5(input: String): String {
        val inputBytes = input.toByteArray()
        val byteLength = inputBytes.size //长度(字节长度)

        var groupCount = byteLength / 64 //完整分组的个数

        var groups: LongArray

        //处理每一个完整的分组
        for (step in (0 until groupCount)) {
            groups = divGroup(inputBytes, step * 6)
            trans(groups) //处理分组,核心算法
        }

        val rest = byteLength % 64
        val tempBytes = ByteArray(64) { 0 }
        if (rest <= 56) {
            for (i in 0 until rest) {
                tempBytes[i] = inputBytes[byteLength - rest + 1]
            }
            if (rest < 56) {
                tempBytes[rest] = (1 shl 7).toByte()
                for (i in 1 until 56 - rest) {
                    tempBytes[rest + 1] = 0
                }
            }
            var len = (byteLength shl 3).toLong()
            for (i in 0 until 8) {
                tempBytes[56 + i] = (len and 0xFFL).toByte()
                len = len shr 8
            }
            groups = divGroup(tempBytes, 0)
            trans(groups)
        } else {
            for (i in 0 until rest) {
                tempBytes[i] = inputBytes[byteLength - rest + 1]
            }
            tempBytes[rest] = (1 shl 7).toByte()
            for (i in (rest + 1) until 64) {
                tempBytes[i] = 0
            }
            groups = divGroup(tempBytes, 0)
            trans(groups)

            for (i in 0 until 56) {
                tempBytes[i] = 0
            }
            var len = (byteLength shl 3).toLong()
            for (i in 0 until 8){
                tempBytes[56 + i] = (len and 0xFFL).toByte()
                len = len shr 8
            }
            groups = divGroup(tempBytes,0)
            trans(groups)
        }

        var resStr = ""
        var temp = 0L
        for (i in 0 until 4){
            for (j in 0 until 4){
                temp = result[i] and 0x0FL
                val a = hex[temp.toInt()]
                result[i] = result[i] shr 4
                temp = result[i] and 0x0FL
                resStr += hex[temp.toInt()].toString() + a.toString()
                result[i] = result[i] shr 4
            }
        }
        return resStr
    }

    /**
     * 将每个大组(512bit)分为16个小组,每个小组64(bit),每个小组恰好是一个long数据
     */
    private fun divGroup(inputBytes: ByteArray, index: Int): LongArray {
        val result = LongArray(16) { 0 }
        for (i in 0 until 16) {
            result[i] = b2iu(inputBytes[4 * i + index]) or
                    (b2iu(inputBytes[4 * i + 1 + index]) shl 8) or
                    (b2iu(inputBytes[4 * i + 2 + index]) shl 16) or
                    (b2iu(inputBytes[4 * i + 3 + index]) shl 24)
        }
        return result
    }

    /**
     * 这个时候不存在符号位(符号位存储不再代表正负),所以Byte转为Long的时候需要处理下
     */
    private fun b2iu(b: Byte): Long {
        return if (b < 0) ((b and 0x7F.toByte()) + 128).toLong() else b.toLong()
    }

    /**
     * 核心计算方法,四轮运算
     */
    private fun trans(groups: LongArray) {
        var a = result[0]
        var b = result[1]
        var c = result[2]
        var d = result[3]

        /*第一轮*/
        a = FF(a, b, c, d, groups[0], S11, 0xd76aa478L) /* 1 */
        d = FF(d, a, b, c, groups[1], S12, 0xe8c7b756L) /* 2 */
        c = FF(c, d, a, b, groups[2], S13, 0x242070dbL) /* 3 */
        b = FF(b, c, d, a, groups[3], S14, 0xc1bdceeeL) /* 4 */
        a = FF(a, b, c, d, groups[4], S11, 0xf57c0fafL) /* 5 */
        d = FF(d, a, b, c, groups[5], S12, 0x4787c62aL) /* 6 */
        c = FF(c, d, a, b, groups[6], S13, 0xa8304613L) /* 7 */
        b = FF(b, c, d, a, groups[7], S14, 0xfd469501L) /* 8 */
        a = FF(a, b, c, d, groups[8], S11, 0x698098d8L) /* 9 */
        d = FF(d, a, b, c, groups[9], S12, 0x8b44f7afL) /* 10 */
        c = FF(c, d, a, b, groups[10], S13, 0xffff5bb1L) /* 11 */
        b = FF(b, c, d, a, groups[11], S14, 0x895cd7beL) /* 12 */
        a = FF(a, b, c, d, groups[12], S11, 0x6b901122L) /* 13 */
        d = FF(d, a, b, c, groups[13], S12, 0xfd987193L) /* 14 */
        c = FF(c, d, a, b, groups[14], S13, 0xa679438eL) /* 15 */
        b = FF(b, c, d, a, groups[15], S14, 0x49b40821L) /* 16 */

        /*第二轮*/
        a = GG(a, b, c, d, groups[1], S21, 0xf61e2562L) /* 17 */
        d = GG(d, a, b, c, groups[6], S22, 0xc040b340L) /* 18 */
        c = GG(c, d, a, b, groups[11], S23, 0x265e5a51L) /* 19 */
        b = GG(b, c, d, a, groups[0], S24, 0xe9b6c7aaL) /* 20 */
        a = GG(a, b, c, d, groups[5], S21, 0xd62f105dL) /* 21 */
        d = GG(d, a, b, c, groups[10], S22, 0x2441453L) /* 22 */
        c = GG(c, d, a, b, groups[15], S23, 0xd8a1e681L) /* 23 */
        b = GG(b, c, d, a, groups[4], S24, 0xe7d3fbc8L) /* 24 */
        a = GG(a, b, c, d, groups[9], S21, 0x21e1cde6L) /* 25 */
        d = GG(d, a, b, c, groups[14], S22, 0xc33707d6L) /* 26 */
        c = GG(c, d, a, b, groups[3], S23, 0xf4d50d87L) /* 27 */
        b = GG(b, c, d, a, groups[8], S24, 0x455a14edL) /* 28 */
        a = GG(a, b, c, d, groups[13], S21, 0xa9e3e905L) /* 29 */
        d = GG(d, a, b, c, groups[2], S22, 0xfcefa3f8L) /* 30 */
        c = GG(c, d, a, b, groups[7], S23, 0x676f02d9L) /* 31 */
        b = GG(b, c, d, a, groups[12], S24, 0x8d2a4c8aL) /* 32 */

        /*第三轮*/
        a = HH(a, b, c, d, groups[5], S31, 0xfffa3942L) /* 33 */
        d = HH(d, a, b, c, groups[8], S32, 0x8771f681L) /* 34 */
        c = HH(c, d, a, b, groups[11], S33, 0x6d9d6122L) /* 35 */
        b = HH(b, c, d, a, groups[14], S34, 0xfde5380cL) /* 36 */
        a = HH(a, b, c, d, groups[1], S31, 0xa4beea44L) /* 37 */
        d = HH(d, a, b, c, groups[4], S32, 0x4bdecfa9L) /* 38 */
        c = HH(c, d, a, b, groups[7], S33, 0xf6bb4b60L) /* 39 */
        b = HH(b, c, d, a, groups[10], S34, 0xbebfbc70L) /* 40 */
        a = HH(a, b, c, d, groups[13], S31, 0x289b7ec6L) /* 41 */
        d = HH(d, a, b, c, groups[0], S32, 0xeaa127faL) /* 42 */
        c = HH(c, d, a, b, groups[3], S33, 0xd4ef3085L) /* 43 */
        b = HH(b, c, d, a, groups[6], S34, 0x4881d05L) /* 44 */
        a = HH(a, b, c, d, groups[9], S31, 0xd9d4d039L) /* 45 */
        d = HH(d, a, b, c, groups[12], S32, 0xe6db99e5L) /* 46 */
        c = HH(c, d, a, b, groups[15], S33, 0x1fa27cf8L) /* 47 */
        b = HH(b, c, d, a, groups[2], S34, 0xc4ac5665L) /* 48 */

        /*第四轮*/
        a = II(a, b, c, d, groups[0], S41, 0xf4292244L) /* 49 */
        d = II(d, a, b, c, groups[7], S42, 0x432aff97L) /* 50 */
        c = II(c, d, a, b, groups[14], S43, 0xab9423a7L) /* 51 */
        b = II(b, c, d, a, groups[5], S44, 0xfc93a039L) /* 52 */
        a = II(a, b, c, d, groups[12], S41, 0x655b59c3L) /* 53 */
        d = II(d, a, b, c, groups[3], S42, 0x8f0ccc92L) /* 54 */
        c = II(c, d, a, b, groups[10], S43, 0xffeff47dL) /* 55 */
        b = II(b, c, d, a, groups[1], S44, 0x85845dd1L) /* 56 */
        a = II(a, b, c, d, groups[8], S41, 0x6fa87e4fL) /* 57 */
        d = II(d, a, b, c, groups[15], S42, 0xfe2ce6e0L) /* 58 */
        c = II(c, d, a, b, groups[6], S43, 0xa3014314L) /* 59 */
        b = II(b, c, d, a, groups[13], S44, 0x4e0811a1L) /* 60 */
        a = II(a, b, c, d, groups[4], S41, 0xf7537e82L) /* 61 */
        d = II(d, a, b, c, groups[11], S42, 0xbd3af235L) /* 62 */
        c = II(c, d, a, b, groups[2], S43, 0x2ad7d2bbL) /* 63 */
        b = II(b, c, d, a, groups[9], S44, 0xeb86d391L) /* 64 */

        /*加入到之前计算的结果当中*/
        result[0] += a
        result[1] += b
        result[2] += c
        result[3] += d
        result[0] = result[0] and 0xFFFFFFFFL
        result[1] = result[1] and 0xFFFFFFFFL
        result[2] = result[2] and 0xFFFFFFFFL
        result[3] = result[3] and 0xFFFFFFFFL
    }
}
 

SHA1算法

用法

    fun getSHA1(str: String): String {
        kotlin.runCatching {
            val sha = MessageDigest.getInstance("SHA-1")
            sha.update(str.toByteArray())
            return BigInteger(1, sha.digest()).toString(16)
        }
        return ""
    }

测试代码

    @Test
    fun testSha1() {
        val begin = System.currentTimeMillis()
        val result = LKUtil.getSHA1("123456789012345678990")
        val end = System.currentTimeMillis()
        println("cost:" + (end - begin) + ":" + result);
    }

测试结果

cost:46:3ae9b112ed472836b0fdd6b94d53b4fd31484d19

MD5与SHA1算法的比较

详细的比较结果请参看文档https://www.cnblogs.com/scu-cjx/p/6878853.html

简单来看,结果如下

差异 MD5 SHA1
摘要长度 128 160
运算时间 短(28ms) 长(46ms)

 

 

2. 对称加密

对称加密算法最主要的特点是加密秘钥和解密秘钥相同。相对来说,对称加密的加密速度更快,常见的应用场景有https在传输阶段的加密模式。

常见的对称加密算法有,AES和DES

  • DES:比较老的算法,一共有三个参数入口(原文、秘钥、加密模式)。而3DES只是DES的一种模式,是以DES为基础更安全的变形。
  • AES:高级加密标准,新一代标准,加密速度更快,安全性更高

AES加密算法

AES是分组密码,也就是把明文分成一组一组的,每组长度相同,每次加密一组数据,直到加密完整个明文。在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个Byte。秘钥的长度可以使用128位,192位或256位。秘钥的长度不同,推荐加密轮速也不同,具体如下表所示。

AES 秘钥长度(Byte) 分组长度(Byte) 加密轮数
AES-128 4 4 10
AES-192 6 4 12
AES-256 8 4 14

加密的详细实现参看文章https://blog.csdn.net/qq_28205153/article/details/55798628

使用方法如下(Kotlin)

@Test
    fun testAES() {
        val content = "Hello World"
        val key = "123456"

        val begin = System.currentTimeMillis()
        val bytes = encryptByAes(content.toByteArray(), key.toByteArray())
        val mid = System.currentTimeMillis()
        val source = decryptByAes(bytes, key.toByteArray())
        val end = System.currentTimeMillis()
        println("source:${String(source)} encrypt:${mid - begin} decrypt:${end - mid}")
    }

    private fun generateAesKey(key: ByteArray): SecretKey {
        // 根据指定的RNG算法,创建安全随机数生成器
        val random = SecureRandom.getInstance("SHA1PRNG")
        // 设置 秘钥key的字节数组,作为安全随机数生成器的种子
        random.setSeed(key)

        // 创建AES算法生成器
        val gen = KeyGenerator.getInstance("AES")
        // 初始化算法生成器
        gen.init(128, random)

        //生成AES秘钥对象
        return gen.generateKey()
    }

    private fun encryptByAes(source: ByteArray, key: ByteArray): ByteArray {
        //生成秘钥对象
        val secKey = generateAesKey(key)
        //获取AES密码器
        val cipher = Cipher.getInstance("AES")
        // 初始化密码器(加密模型)
        cipher.init(Cipher.ENCRYPT_MODE, secKey)

        //加密数据, 返回密文
        return cipher.doFinal(source)
    }

    private fun decryptByAes(source: ByteArray, key: ByteArray): ByteArray {
        // 生成秘钥对象
        val secKey = generateAesKey(key)

        // 获取AES密码器
        val cipher = Cipher.getInstance("AES")
        //初始AES密码器
        cipher.init(Cipher.DECRYPT_MODE, secKey)
        //解密数据,返回明文
        return cipher.doFinal(source)
    }

看下输出

source:Hello World 加密耗时:105ms 解密耗时:0ms

DES加密算法

详细的介绍可以参看文章https://www.cxyxiaowu.com/1478.html

其中,加密流程可以概括为

这里需要注意的是,原始秘钥长度必须为64位,否则会报错

看一下用法

    @Test
    fun testDes() {
        val content = "Hello World"
        val key = "12345678"

        val begin = System.currentTimeMillis()
        val bytes = encryptBytesByDes(content.toByteArray(), key.toByteArray())
        val mid = System.currentTimeMillis()
        val source = decryptByDes(bytes, key.toByteArray())
        val end = System.currentTimeMillis()
        println("source:${String(source)} 加密后长度:${bytes.size} 加密耗时:${mid - begin}ms 解密耗时:${end - mid}ms")
    }

    private fun generateDesKey(key: ByteArray): SecretKey {
        //根据给定的原始秘钥来生成秘钥
        val key = SecretKeySpec(key, "DES")
        return key
    }

    private fun encryptBytesByDes(source: ByteArray, sourceKey: ByteArray): ByteArray {
        val key = generateDesKey(sourceKey)
        val cipher = Cipher.getInstance("DES")
        cipher.init(Cipher.ENCRYPT_MODE, key)
        return cipher.doFinal(source)
    }

    private fun decryptByDes(source: ByteArray, sourceKey: ByteArray): ByteArray {
        val key = generateDesKey(sourceKey)
        val cipher = Cipher.getInstance("DES")
        cipher.init(Cipher.DECRYPT_MODE, key)
        return cipher.doFinal(source)
    }

看一下输出

source:Hello World 加密后长度:16 加密耗时:121ms 解密耗时:0ms

可以看到,他的加密耗时是要比AES要长的

我们补一个关于AES和DES算法比较的图,来自于https://yq.aliyun.com/articles/156277

名称 秘钥长度 运算速度 安全性 资源消耗  
DES 56位 较快  
3DES 112位或156位  
AES 128、192、256位  

 

 

 

 

3. 非对称加密

非对称加密是指公钥和私钥不同的加密方式,用公钥加密,然后用私钥解密。或者用私钥加密,用公钥解密。

与对称加密比起来,非对称加密安全性更好,私钥完全是自己保存的,但是一般来说加密和解密速度更慢,一般只适用于对少量数据进行加密

RSA

关于原理解释可以参看 https://blog.csdn.net/qy20115549/article/details/83105736

看一下怎么调用

    @Test
    fun testRsa() {
        val begin = System.currentTimeMillis()
        val pair = genRsaPair()

        val publishKey = pair.get(0)!!
        val privateKey = pair.get(1)!!

         val mid = System.currentTimeMillis()
        println("publishKey:${publishKey} \n\n privateKey:$privateKey \n\n")

        val source = "Hello World"
        val encodeString = encodeByPublishRsa(source, publishKey)

        val encodeOver = System.currentTimeMillis()
        println("encodeString:$encodeString \n\n")

        val decodeString = decodeByRsa(encodeString, privateKey)
        println("decodeString:$decodeString \n\n")

        val decodeOver = System.currentTimeMillis()
        println("gen key cost:${mid - begin} encode cost:${encodeOver - mid} decode cost:${decodeOver - encodeOver}")
    }

    /**
     * 生成RSA的秘钥对
     */
    private fun genRsaPair(): HashMap<Int, String> {
        val keyPairGen = KeyPairGenerator.getInstance("RSA")
        //初始化秘钥对生成器, 秘钥大小为96-1024位
        keyPairGen.initialize(1024, SecureRandom())

        //生成一个秘钥对, 保存在keyPair中
        val keyPair = keyPairGen.generateKeyPair()

        val privateKey = keyPair.private as RSAPrivateKey //私钥
        val publishKey = keyPair.public as RSAPublicKey //公钥

        //得到公钥字符串
        val publishKeyString = java.util.Base64.getEncoder().encodeToString(publishKey.encoded)
        //得到私钥字符串
        val privateKeyString = java.util.Base64.getEncoder().encodeToString(privateKey.encoded)

        return HashMap<Int, String>().apply {
            this[0] = publishKeyString
            this[1] = privateKeyString
        }
    }

    /**
     * 通过rsa加密
     */
    private fun encodeByPublishRsa(source: String, key: String): String {
        val decode = java.util.Base64.getDecoder().decode(key)
        val publishKey = KeyFactory.getInstance("RSA").generatePublic(X509EncodedKeySpec(decode))

        val cipher = Cipher.getInstance("RSA")
        cipher.init(Cipher.ENCRYPT_MODE, publishKey)

        val outStr = java.util.Base64.getEncoder().encodeToString(cipher.doFinal(source.toByteArray()))
        return outStr
    }

    /**
     * 通过RSA解密
     */
    private fun decodeByRsa(source: String, key: String): String {
        val decode = java.util.Base64.getDecoder().decode(key)
        val sourceByte = java.util.Base64.getDecoder().decode(source.toByteArray())
        val privateKey = KeyFactory.getInstance("RSA").generatePrivate(PKCS8EncodedKeySpec(decode))

        val cipher = Cipher.getInstance("RSA")
        cipher.init(Cipher.DECRYPT_MODE, privateKey)

        return String(cipher.doFinal(sourceByte))
    }

看一下输出

publishKey:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCjxcFMouLuHmVZTDjxc0JyGbGPSMp+r7mpgbOOJq/WePieTtelvPxdrnG8fj9HPFV7GAmyAUPPZmUKGV6e8/uoOJ/HKuXKu3NEW+xnaeMU+IKn+EA143h+t8fHnRyq5nO8PuF8bNBzC27mOVvN6oLtVijLxRScXOSsZk6SzQbHlQIDAQAB 

 privateKey:MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKPFwUyi4u4eZVlMOPFzQnIZsY9Iyn6vuamBs44mr9Z4+J5O16W8/F2ucbx+P0c8VXsYCbIBQ89mZQoZXp7z+6g4n8cq5cq7c0Rb7Gdp4xT4gqf4QDXjeH63x8edHKrmc7w+4Xxs0HMLbuY5W83qgu1WKMvFFJxc5KxmTpLNBseVAgMBAAECgYAPPviovr0rd67tqjfe2mEEKDosYZVgR9Gb4xQpFpbl+2sBqctPhZFk0zmJV6NiaU534Bv+8zkx1JFxaD0zxPjXYMCI4hfi2LfB8K0XeCP/wldbpeNuGQ3uZ0hBHUP/HawoRU2O7lviaqoms0o20XQ6Yd8dy+geGi/FhnmGOSMrfQJBAOnMZwuSK3JsEJ2q55YcvL7hEeTKraNEYO+MnV8gSQEAy3N6K5akA/y5a+Hs987RxGU7LNFLwysS3ax8pKTS8ScCQQCzUwi8DuTJx2/P63l7QsLfv0trEarOR7FOREu0ZK4GtkoRG1uU+ZZZ64Hq+BWGL3enj4SO6l/VImzn7q+RAL7jAkBmArSXXOCuHS6mzLIdUk6cbnGzRSe8DBLLkqv7nIed823R5eVs5gWDWJgUzKNXTzmE/evRKmBuw92K7BueexeTAkEAno26WVzp2acnK7XOUbfzyhW/v0l9tqoZEVS9gyDJ5lFjJ8ECtrP/xj2/P1xe26g4qcTxtdNxLGgl1uRqA1GfdQJBAI7qc3l+77K3+Modr8boNqIIfoZqKKbwrPQRphgp/tUPZ80qLV2NSKT5K3e2EoI2DZ923IZPSAYV/ldN09H57HU= 


encodeString:m7r4U+T3L8/Oa+BfvQ3Z2iXhlrf/nMTYinDvziGjFb+RfJWpGGcNzdEIYH5ruP5PTJnwXN4MOSS7M5nV4DiBjolwy+rlcA3460ubJqKXEHvGyqtxZABa839dKFwxysULJL2TOQEtWq2zlccdP/qTdALnxhmt62VVQin1r4jVlF4= 


decodeString:Hello World 


gen key cost:124 encode cost:34 decode cost:2

ps: 这么看非对称加密的时间开销也不大啊。。可能是因为我的数据量太小的原因吧

在代码中,我们可以看到X509和PKCS, 关于这种的解释如下

  • X509是密码学中的公钥证书标准,含有公钥,分身信息和签名信息,详细参看维基百科吧 https://zh.wikipedia.org/wiki/X.509
  • PKCS 是由美国RSA数据安全公司及其合作伙伴制定的一组公钥密码学标准,其中包括证书申请、证书更新、证书作废表发布、扩展证书内容以及数字签名数字信封的格式等方面的一系列相关协议

DSA

既 Digital Signature Algorithm,数字签名算法,他是由美国国家标准与技术研究所(NIST)与1991年提出。和 RSA 不同的是 DSA 仅能用于数字签名,不能进行数据加密解密,其安全性和RSA相当,但其性能要比RSA快。

详细的不介绍了,累死了

猜你喜欢

转载自blog.csdn.net/weixin_43662090/article/details/112978442
今日推荐