专栏首页I0ganDES加解密-简单原理与go语言实现
原创

DES加解密-简单原理与go语言实现

注: 这个是最近的工程实践作业,根据书上理解原理后采用golang语言来实现的。

参考: [1] 应用密码学 (卓越工程师计划) 张仕斌 编著

DES加密原理

1. 对明文进行分组-> 每8字节为一组

2. 对明文进行IP置换,接下来就像轮结构变换了

3. 轮结构变换

公式: Li = R(i - 1), Ri = L(i - 1) ^ F(R(i - 1), Ki)

其中L是左边32bit,也就是低32bit,R为高32bit,这里采用大端表示。

F为轮加密函数,包括如下

1. R(i - 1)进行E盒拓展为48bit

2. 与子密钥进行异或

3. 再进行S盒子压缩为32bit

4. 再对这32bit进行P盒置换

经过一次轮变化输出的32bit进行与L- i异或的到Ri, 而Li则为 R(i - 1)

依次不断重复以上轮加密。

但由于涉及每论结构变换的时候,子密钥都要得重新生成,

子密钥生成过程如下:

1. 经过置换选择PC - 1从64bit变换至56bit,将8bit的校验位去掉。

2. 的到的数据分成两组,C0和D0,各28bit

3. C0与D0分别循环左移,得到C1和D0组装为56bit进行置换选择PC - 2的到子密钥1

4. 再对C1和D1的到C2和D2分别循环左移组装为56bit进行置换选择PC - 2的到子密钥2

不断重复上面步骤16次,即可得到16轮次的子密钥。

再采用这些子密钥作为轮结构变换的每轮的子密钥,经过16论后,即可获得加密后64bit的密文了。

经过16轮加密后,32bit交换组装为64bit,再进行IP逆向置换。

DES加密原理

与加密原理相同,唯一不同的地方就是生成子密钥后,在轮加密的使用顺序相反。

开发环境

Arch linux

Linux version 5.12.12-arch1-1 (linux@archlinux)

Golang

go version go1.16.5 linux/amd64

代码准备

为了能够更好的调试,下面我增加了两个主要函数,binStrToIntB和PrintInt64B,binStrToIntB功能是将字符串以大端方式转化为64bit的数值类型,PrintInt64B是将64bit的数值类型以大端方式进行打印出来,也就是左边为低位,右边为高位,方便后续调试与查看。

测试如下

IP置换实现

IP置换表中的值代表是第几bit的值,采用目前第几个bit索引值i1 进行查IP置换表后得到bit索引 i2,再根据这个i2查本身自己对应的该bit位,替换当前 i1位置的bit值。

根据教科书上的例子进行编写与测试

IP置换实现

测试:数据来自教科书

E盒拓展置换实现

通过得到的R32 bit进行E盒拓展置换。

从32bit拓展到48bit,将该eBox表中对于的bit位放入该索引bit位置中

实现代码如下

测试

将E盒拓展的48bit结果与子密钥异或传入S盒置换中。

S盒压缩实现

S 盒压缩,将48bit压缩为32bit

将48bit分为8组,每组6bit

该组的第一个bit位与第6个bit位 组成S盒行号

中间4bit位 组成S盒列号

计算公式:

r = b1 * 2 + b6

c = b2 << 3 + b3 << 2 + b3 << 1 + b4

根据行号和列好查询的到4bit的二进制数,对该二进制数进行大端处理即可完毕S盒

测试如下

P盒置换实现

原理与之前的IP置换一样,只是位数和表不同。

测试

子密钥匙生成-过程

子密钥生成部分,获取64bit的密钥后,经过PC1置换,获取56bit有效位,分成两组28bit,分别C0,D0。

C0,D0通过循环左移得到C1,D1,组装在一起,经过PC2置换得到第一轮子密钥。

C1与D1经过循环左移,得到C2,D2,组装在一起,经过PC2置换得到第二轮密钥,以此类推,得到下一轮密钥。

子密钥匙生成-置换选择PC1

将64bit的密钥取出56bit的有效位。

子密钥匙生成-循环左移

经过PC1置换后,将56bit拆分为C0和D0,各28bit,再经过置换选择PC2。

结尾处理-IP逆置换

IP逆置换,经过16轮变换之后,得到64bit数据,最后一步是IP逆置换。

IP逆置换正好是IP置换的逆。

经过IP逆置换后,即完成本组加密。

整体加密实现

密钥生成器: 负责生成16轮次密钥

单轮次加密

加密实现

代码有点长,思路是先填充为8的倍数长度,依次对没8字节进行分组加密。

先进行16轮所需密钥生成->IP置换-> 16次轮加密->IP逆置换

解密实现

与加密思路一样,唯一不同的地方在于密钥生成后在轮加密使用时的顺序相反。

Des加解密钥完整测试

运行

完整代码

package main

import (
    "fmt" 
)

// 是否为debug模式
var debug bool = false

// 二进制字符串转换至 Int, Left Low, Right High, Bigger模式输入
func BinStrToIntB(bin string) uint64 {
   var ret uint64 = 0 
   length := len(bin)

    j := 0
   for i := 0; i < length; i ++ {
        if(bin[i] == ' ') {
            continue
        }
        ret |= (uint64)(bin[i] - '0' ) << j
        j ++
   }
   return ret
}

// 以大端模式打印64位二进制bit位
func PrintInt64B(str string, num uint64) {
   // 反转bit位
    var out uint64 = 0 
    t := 64
    for i := 0; i < t; i ++ {
        out |= ((uint64)((num >> i )& 0x1)) << (t - i - 1)
    }
    fmt.Printf("%s : %064b\n", str, out)
}

// 以大端模式打印56位二进制bit位
func PrintInt56B(str string, num uint64) {
   // 反转bit位
    var out uint64 = 0 
    t := 56
    for i := 0; i < t; i ++ {
        out |= ((uint64)((num >> i )& 0x1)) << (t - i - 1)
    }
    fmt.Printf("%s : %056b\n", str, out)
}

// 以大端模式打印48位二进制bit位
func PrintInt48B(str string, num uint64) {
   // 反转bit位
    var out uint64 = 0 
    t := 48
    for i := 0; i < t; i ++ {
        out |= ((uint64)((num >> i )& 0x1)) << (t - i - 1)
    }
    fmt.Printf("%s : %048b\n", str, out)
}

// 以大端模式打印32位二进制bit
func PrintInt32B(str string, num uint32) {
   // 反转bit位
    var out uint64 = 0 
    t := 32
    for i := 0; i < t; i ++ {
        out |= ((uint64)((num >> i )& 0x1)) << (t - i - 1)
    }
    fmt.Printf("%s : %032b\n", str, out)
}

// 以大端模式打印28位二进制bit
func PrintInt28B(str string, num uint32) {
   // 反转bit位
    var out uint64 = 0 
    t := 28
    for i := 0; i < t; i ++ {
        out |= ((uint64)((num >> i )& 0x1)) << (t - i - 1)
    }
    fmt.Printf("%s : %028b\n", str, out)
}

// IP置换
/*
IP置换表中的值代表是第几bit的值,采用目前第几个bit索引值i1 进行查IP置换表后得到bit索引 i2,再根据这个i2查本身自己对应的该bit位,替换当前 i1位置的bit值。
*/
func IPRplace(num uint64) uint64 {
    var IPTable = [64]uint8 {
        58,50,42,34,26,18,10,2,
        60,52,44,36,28,20,12,4,
        62,54,46,38,30,22,14,6,
        64,56,48,40,32,24,16,8,
        57,49,41,33,25,17,9,1,
        59,51,43,35,27,19,11,3,
        61,53,45,37,29,21,13,5,
        63,55,47,39,31,23,15,7,}
    var out uint64 = 0
    for i := 0; i < 64; i ++ {
        out |= (num >> (uint64(IPTable[i] - 1)) & 0x1) << i
    }
    return out
}

// E盒子拓展:
/*
    从32bit拓展到48bit
    将该eBox表中对于的bit位放入该索引bit位置中
*/
func E_Expand(num uint32) uint64{
	var eBox = [48]uint8{
        32,1 ,2 ,3 ,4 ,5,
        4 ,5 ,6 ,7 ,8 ,9,
        8 ,9 ,10,11,12,13,
        12,13,14,15,16,17,
        16,17,18,19,20,21,
        20,21,22,23,24,25,
        24,25,26,27,28,29,
        28,29,30,31,32,1 ,
    }
    var out uint64 = 0
    for i := 0; i < 48; i ++ {
        out |= (uint64)((num >> (eBox[i] - 1)) & 1) << i
    }
    return out 
}
/*
    S 盒压缩,将48bit压缩为32bit
    将48bit分为8组,每组6bit
    该组的第一个bit位与第6个bit位 组成S盒行号
    中间4bit位 组成S盒列号

    计算公式: 
    r = b1 * 2 + b6
    c = b2 << 3 + b3 << 2 + b3 << 1 + b4

    根据行号和列好查询的到4bit的二进制数,对该二进制数进行大端处理即可完毕S盒
*/
func SBox(num uint64) uint32{
    var sBox = [8][4][16]uint8{
		{{14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7},
        {0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8},
        {4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0},
        {15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13},},

		{{15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10},
        {3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5},
        {0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15},
        {13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9},},

		{{10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8},
        {13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1},
        {13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7},
        {1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12},},

		{{7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15},
        {13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9},
        {10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4},
        {3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14},},

		{{2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9},
        {14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6},
        {4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14},
        {11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3},},

		{{12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11},
        {10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8},
        {9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6},
        {4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13},},

		{{4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1},
        {13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6},
        {1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2},
        {6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12},},

		{{13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7},
        {1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2},
        {7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8},
        {2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11},},
	}

    var out uint32 = 0
    for i := 0; i < 8; i ++ {
        b := (uint8)(num >> (i * 6)) & 0x3f
        r := (b & 1) << 1 + (b >> 5)
        c := ((b >> 1) & 1) << 3 + ((b >> 2) & 1) << 2 + ((b >> 3) & 1) << 1 + ((b >> 4) & 1)
        o := sBox[i][r][c]

        // 由于查表是小端模式,需要转换至大端
        var o2 uint8 = 0

        for j := 0; j < 4; j ++{
            o2 |= ((o >> j) & 1) << (3 - j)
        }

        out |= uint32(o2) << (i * 4)
        
        if debug == true {
            //fmt.Printf("b: %06b r: %d c: %d, o: %04b o2: %04b\n", b, r, c, o, o2)
        }
    }

    return out
}
/*
    P和置换
    与IP置换原理一样
*/
func PBox(num uint32) uint32 {
	var pTable = [32]uint8{
        16,7,20,21,
        29,12,28,17,
        1,15,23,26,
        5,18,31,10,
        2,8,24,14,
        32,27,3,9,
        19,13,30,6,
        22,11,4,25,
    }
    var out uint32 = 0
    for i := 0; i < 32; i ++ {
        out |= (num >> (uint32(pTable[i] - 1)) & 0x1) << i
    }
    return out
}


/*
    子密钥生成部分
    获取64bit的密钥后,经过PC1置换,获取56bit有效位,分成两组28bit,分别为C0,D0。
    C0,D0通过循环左移得到C1,D1,组装在一起,经过PC2置换得到第一轮子密钥。
    
    C1与D1经过循环左移,得到C2,D2,组装在一起,经过PC2置换得到第二轮密钥,以此类推,得到下一轮密钥。
*/

/*
    将64bit的密钥压缩生成56bit
*/
func PC1(num uint64) uint64{
	var p1Table = [56]uint8 {
        57,49,41,33,25,17,9,
        1,58,50,42,34,26,18,
        10,2,59,51,43,35,27,
        19,11,3,60,52,44,36,
        63,55,47,39,31,23,15,
        7,62,54,46,38,30,22,
        14,6,61,53,45,37,29,
        21,13,5,28,20,12,4 ,
    }
    var out uint64 = 0
    for i := 0; i < 56; i++ {
        out |= (uint64)((num >> (p1Table[i] - 1)) & 1) << i;
    }
    return out
}

/*
    将56bit的密钥压缩生成48bit
*/
func PC2(num uint64) uint64{
	var p2Table = [48]uint8{
        14,17,11,24,1,5,
        3,28,15,6,21,10,
        23,19,12,4,26,8,
        16,7,27,20,13,2,
        41,52,31,37,47,55,
        30,40,51,45,33,48,
        44,49,39,56,34,53,
        46,42,50,36,29,32,
    }
    var out uint64 = 0
    for i := 0; i < 48; i++ {
        out |= (uint64)(num >> (p2Table[i] - 1) & 1) << i;
    }
    return out
}
/*
    循环左移
*/

func ShiftLeft(num uint32, times int) uint32 {
    if(times > 16 || times < 1) {
        fmt.Println("ShiftLeft Error")
        return num
    }

    var shiftTable = [16]int {
        1, 1, 2, 2, 2, 2, 2, 2,
        1, 2, 2, 2, 2, 2, 2, 1,
    }
    // 由于在数值中,高位在左,低位在右,所以采用右移,在大端模式下是左移
    var out uint32 = num
    for i := 0; i < shiftTable[times - 1]; i++ {
        h := num & 1 // 获取最低位
        out >>= 1 
        out |= h << 27 // 低位补高位
    }
    return out 
}

/*
    IP逆置换,经过16轮变换之后,得到64bit数据,最后一步是IP逆置换。
    IP逆置换正好是IP置换的逆。
*/

func InverseIPRplace(num uint64) uint64 {
    var IPTable = [64]uint8 {
        40,8,48,16,56,24,64,32,
        39,7,47,15,55,23,63,31,
        38,6,46,14,54,22,62,30,
        37,5,45,13,53,21,61,29,
        36,4,44,12,52,20,60,28,
        35,3,43,11,51,19,59,27,
        34,2,42,10,50,18,58,26,
        33,1,41,9,49,17,57,25,}

    var out uint64 = 0
    for i := 0; i < 64; i ++ {
        out |= (num >> (uint64(IPTable[i] - 1)) & 0x1) << i
    }
    return out
}

// 单轮加密实现
// m 为R(i - 1), key为本轮次子密钥
func SingalRound(l uint32, r uint32, key uint64) uint32 {
    o := E_Expand(r)
    o ^= key
    so := SBox(o)
    so = PBox(so)
    return so ^ l;
}

// 子密钥生成器
func DesKeyGen(key uint64) [16]uint64 {
    var out = [16]uint64 {0}
    o := PC1(key)
    l := (uint32)(o & 0xfffffff) // 获取低28bit
    r := (uint32)(o >> 28)       // 获取高28bit

    for i := 1; i <= 16; i++ {
        l = ShiftLeft(l, i)
        r = ShiftLeft(r, i)
        o = uint64(l)
        o |= (uint64)(r << 28)
        o = PC2(o)
        out[i - 1] = o
    }
    return out
}

// Des加密函数实现
func DesEncode(m []byte, key uint64) []byte {
    keys := DesKeyGen(key)
    out := make([]byte, 0)

    length := len(m)
    if(length % 8 != 0) { // 补充0
        for i := 0; i < (8 - (length % 8)); i ++ {
            m = append(m, 0)
        }
        length = len(m)
    }

    // 每8字节进行加密
    for i := 0; i < (length / 8); i++ {
        var d uint64 = 0

        // 将8字节转化为uint64类型
        for j := 0; j < 8; j++ {
            var c uint8 = m[i * 8 + j] // 获取当前字节
            // 由是小端模式,需要转换至大端
            var o2 uint8 = 0
            for k := 0; k < 8; k ++{
                o2 |= ((c >> k) & 1) << (7 - k)
            }
           d |= uint64(o2) << (j * 8)
        }
        //fmt.Printf("o  : %064b\n", d)
        //PrintInt64B("m ", d)

        // IP置换
        o := IPRplace(d)
        l := uint32(o)
        r := uint32(o >> 32)
        t := uint32(0)

        // 轮加密
        for j := 0; j < 16; j ++ {
            t = r
            r = SingalRound(l, r, keys[j])
            l = t
        }

        //PrintInt32B("l0 ", l)
        //PrintInt32B("r0", r)
        // 左右交换合并
        d = uint64(r)
        d |= uint64(l) << 32

        //PrintInt64B("r0", d)

        // IP逆向置换
        d = InverseIPRplace(d)
        //PrintInt64B("IpInverse: ", d)

        // 追加到Bytes

        // 将uint64转化为8字节
        for j := 0; j < 8; j++ {
            //var c uint8 = m[i * 8 + j] // 获取当前字节
            // 大端模式,需要转换至小端
            c := uint8(d >> (j * 8) & 0xff)
            var o2 uint8 = 0
            for k := 0; k < 8; k ++{
                o2 |= ((c >> k) & 1) << (7 - k)
            }
            out = append(out, o2)
           //d |= uint64(o2) << (j * 8)
        }
    }

    //GetUint64ByBytes(&m[8])

    //IPRplace()
    return out
}

// Des解密函数实现
func DesDecode(m []byte, key uint64) []byte {
    keys := DesKeyGen(key)
    out := make([]byte, 0)
    length := len(m)

    // 每8字节进行加密
    for i := 0; i < (length / 8); i++ {
        var d uint64 = 0

        // 将8字节转化为uint64类型
        for j := 0; j < 8; j++ {
            var c uint8 = m[i * 8 + j] // 获取当前字节
            // 由是小端模式,需要转换至大端
            var o2 uint8 = 0
            for k := 0; k < 8; k ++{
                o2 |= ((c >> k) & 1) << (7 - k)
            }
           d |= uint64(o2) << (j * 8)
        }

        // IP置换
        o := IPRplace(d)
        l := uint32(o)
        r := uint32(o >> 32)
        t := uint32(0)

        // 轮加密
        for j := 0; j < 16; j ++ {
            t = r
            r = SingalRound(l, r, keys[15 - j]) // 密钥顺序变化
            l = t
        }

        // 左右交换合并
        d = uint64(r)
        d |= uint64(l) << 32

        //PrintInt64B("r0", d)

        // IP逆向置换
        d = InverseIPRplace(d)
        //PrintInt64B("IpInverse: ", d)

        // 追加到Bytes

        // 将uint64转化为8字节
        for j := 0; j < 8; j++ {
            //var c uint8 = m[i * 8 + j] // 获取当前字节
            // 大端模式,需要转换至小端
            c := uint8(d >> (j * 8) & 0xff)
            var o2 uint8 = 0
            for k := 0; k < 8; k ++{
                o2 |= ((c >> k) & 1) << (7 - k)
            }
            out = append(out, o2)
           //d |= uint64(o2) << (j * 8)
        }
    }

    return out
}

func Test() {
    str := "01100011 01101111 01101101 01110000 01110101 01110100 01100101 01110010"

    subkey := "010100 000010 110010 101100 010101 000010 001101 000111"

    o := BinStrToIntB(str)

    key := BinStrToIntB(subkey)

    fmt.Printf("字符串: %s\n", str)
    fmt.Printf("Little: %064b\n", o)

    PrintInt64B("Input  ", o)
    o = IPRplace(o)
    PrintInt64B("IPTable ", o)

    l := uint32(o)
    r := uint32(o >> 32)
    PrintInt32B("l0 ", l)
    PrintInt32B("r0", r)

    PrintInt32B("E_Expand in  ", r)
    o = E_Expand(r)
    PrintInt48B("E_Expand out ", o)

    fmt.Println("\nS盒实现")
    PrintInt48B("key ", key)

    si := o ^ key
    PrintInt48B("SBox in ", si)

    so := SBox(si)
    PrintInt32B("SBox out ", so)

    po := PBox(so)
    PrintInt32B("PBox out ", po)

    l = l ^ po // 作为下一轮 l
    PrintInt32B("l1 ", l)

    fmt.Println("子密钥生成实现: 输入01234567")
    subkey = "00110000 00110001 00110010 00110011 00110100 00110101 00110110 00110111"
    key = BinStrToIntB(subkey)
    PrintInt64B("key ", key)
    o = PC1(key)
    PrintInt56B("PC1 ", o)
    l = (uint32)(o & 0xfffffff) // 获取低28bit
    r = (uint32)(o >> 28) // 获取高28bit
    PrintInt28B("l ", l)
    PrintInt28B("r ", r)

    fmt.Println("循环左移")
    l = ShiftLeft(l, 1)
    PrintInt28B("l ", l)

    fmt.Println("IP逆置换")
    str = "11111111 10111000 01110110 01010111 00000000 11111111 00000110 10000011"
    o = BinStrToIntB(str)
    PrintInt64B("Input      ", o)
    o = InverseIPRplace(o)
    PrintInt64B("InverseIP  ", o)
}

func main() {
    //Test()
    data := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 'A', 'D'}
    var key uint64 = 0x1234
    fmt.Print("加密前data")
    fmt.Println(data)
    fmt.Printf("key: 0x%X\n", key)

    out := DesEncode(data, key)
    fmt.Println("加密后")
    fmt.Print(out)

    out = DesDecode(out, key)
    fmt.Printf("\n解密后")
    fmt.Print(out)
}

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Python DES加密实现原理及实例解析

    ​首先说一下置换的意思,比如说有5678这个字符串,置换表为2143,置换表中的数表示的是位置,所以字符串变成6587。所有的置换表在程序中。(S盒置换不一样,...

    砸漏
  • [Go] go语言使用dgrijalva/jwt-go 实现加解密jwt

    陶士涵
  • 时代新秀golang--golang加密算法之DES

    业务需要对接接口, 采用DES加密方式加密, 于是google一下go的DES加密方式,

    糖果
  • C语言实现MD5加密,竟如此简单!

    它表示输入任意长度的数据,输出固定长度的数据,它的主要特征是加密过程不需要密钥,并且经过加密的数据无法被解密。

    C语言与CPP编程
  • C语言实现MD5加密,竟如此简单!

    https://www.bilibili.com/video/BV1uy4y1p7on/

    DeROy
  • BlowFish加解密原理与代码实现

    ​ BlowFish 是一个对称加密的加密算法。由Bruce Schneier,1993年设计的。是一个免费自由使用的加密算法。

    IBinary
  • 永强教你加解密:对称篇(一)

    大家好,我是永强,就是老李之前经常给你们说的区块链大神、大学肄业却依然大公司iOS主程一波儿流、只生活在老李口中尚未真实露面的混工资高手、老王的左膀右臂 ———...

    老李秀
  • 【asp.net core 系列】12 数据加密算法

    这一篇我们将介绍一下.net core 的加密和解密。在Web应用程序中,用户的密码会使用MD5值作为密码数据存储起来。而在其他的情况下,也会使用加密和解密的功...

    程序员小高
  • 简单小结密码学入门知识点

      密码,最初的目的是用于对信息加密,计算机领域的密码技术种类繁多。但随着密码学的运用,密码还被用于身份认证、防止否认等功能上。密码是通信双方按约定的法则进行信...

    步履不停凡
  • encyption&decyption

    用户1733354
  • CTF 玩转 Crypto 月度总结

    两个越来,感谢老大哥们的照顾,自己学到挺多的简单的写下 Crypto 各类密码学和 misc 类流量分析的心得。菜鸡一个,不喜勿喷。

    信安之路
  • 从一个需要三个密钥的算法聊聊加解密

    网上瞎逛逛到一个 des 加解密需要三个密钥的,一开始以为是3des,标准3des加密 使用密钥 k1加密一次,k2解密一次,k3加密一次得到加密结果,但是仔细...

    horsley
  • 解码内置不安全“加密芯片”的勒索软件Gomasom

    ? 前言 最近,我们发现了一种新型的勒索软件,因其使用了gmail作为邮箱服务器,故被命名为Gomasom。当用户运行了该勒索软件时,用户的文件会被加密,加密...

    FB客服
  • Python与常见加密方式

    数据加密与解密通常是为了保证数据在传输过程中的安全性,自古以来就一直存在,古代主要应用在战争领域,战争中会有很多情报信息要传递,这些重要的信息都会经过加密,在发...

    润森
  • 敲一天代码了,轻松下吧,精彩 !看人潮如海

    先来首歌曲,耶耶耶..... ? 一边听歌,一遍来看几个算法 一、数字摘要算法 数字摘要也称为消息摘要,它是一个唯一对应一个消息或文本的固定长度的值,它由一个...

    码神联盟
  • DES和AES算法加密解密

    前言:在api传递过程中或者操作cookie中的参数都是明文,很容易暴露一些用户以及私密的信息。

    王念博客
  • java调用JNI总结

    工作中需要用到java调用DES加密解密算法进行通信加密、MAC计算等,原来直接有C语言版的DES算法库可以用,但是java用的不熟,java的DES算法库没用...

    杨永贞
  • PHP实现的简单对称加密与解密方法实例小结

    本文实例讲述了PHP实现的简单对称加密与解密方法。分享给大家供大家参考,具体如下: 方法一:YII自带的加密方法

    用户2323866
  • 懂了!国际算法体系对称算法DES原理

    加密领域主要有国际算法和国密算法两种体系。国密算法是国家密码局认定的国产密码算法。国际算法是由美国安全局发布的算法。由于国密算法安全性高等一系列原因。国内的银行...

    静儿

扫码关注云+社区

领取腾讯云代金券