目录git
Des算法
发展史安全
分组密码算法设计思想app
Des概述ide
初始置换与逆置换函数
Feistel结构工具
轮函数F学习
E扩展测试
密钥加加密
S盒代换
P置换
密钥编排
3Des
优缺点
分组模式
CBC
CFB
OFB
Des的Go实现
明文填充
加密
解密
结果截图
参考
总体结构
明文进行初始置换(Initial Permutation,IP),经过密钥编排算法将密钥拆成16个,进行16轮迭代,最后经过逆置换获得密文。
将输入的64位数据块按位从新组合,把输出分为L0、R0两部分,每部分长32位。
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 |
表中的数字表明新数据中此位置的数据在原数据中的位置,即原数据块的第58位放到新数据的第1位,第50位放到第2位,……依此类推。置换后的数据分为L0和R0两部分。
逆置换就是放回原位置,例如,1位置在40位置,那么逆置换的第一个就是40,我就不一个个画了
40 | ... |
... | ... |
因为初始置换是公开的,没有密码意义。有不少DES实现都去除了,有人认为是当时为了更好放到DES芯片中。
按下述规则进行16次迭代,1≤i≤16
F(,
)以长度为32比特串
做为第一输入,以长度为48比特串
做为第二个输入,产生长度为32比特的输出。
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 |
将扩展为48位,左右两列数据是扩展的数据,扩展的数据是从相邻位置取的一位,可理解为循环队列。靠近32位的位为1,靠近1位的位为32,其他就是下一行首或上一行末。
将的E扩展和
进行异或
使用8个S盒S1……S8,每一个Si是一个固定的4*16阶矩阵,其元素取0~15之间的整数。
给定长度为6的比特串,如Bj=b1b2b3b4b5b6,Sj(Bj)计算以下:
S盒1以下:
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 |
其余的我就不粘贴了,都是公开的,网上能找到,这里只是为了举个例子。
假如,S1的输入Bj为110011
P盒以下:
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 |
长度为32比特串C=C1C2C3C4C5C6C7C8,根据上面的进行替换,原理和前面的IP同样,就是按照P盒放原始数据的多少位,第一个就放C的第16位,依次类推,最后组合一下便可,再也不举例。
前面是迭代加解密,接下来讲下密钥编排,密钥编排就是经过密钥K,得到每轮的密钥ki,过程以下
给定64比特密钥K,根据固定的置换PC-1来处理K获得PC-1(K)=C0D0,其中C0和D0分别由最前和最后28比特组成。下面是PC-1,注意,不包括8,16,24,32,40,48,56和64,前面提到,这些是校验位。
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 |
计算Ci=LSi(Ci-1)和Di=LS(Di-1),且Ki=PC-2(CiDi),LSi表示循环左移两个或一个位置,具体地,若是i=1,2,9,16就移一个位置,不然就移两个位置,PC-2是另外一个固定的置换。下面是PC-2
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 |
以上就是一轮中获取Ki的过程,每轮选取密钥K的不一样48比特进行PC-2的置换,一样是16个矩阵,长宽与PC-2相同,这里就不粘贴了,否则文章太长了。
3Des3DES,顾名思义,使用三次DES算法,有两种模式。
DES-EEE3模式:使用 P->DES加密->DES加密->DES加密->C 进行加密,使用 C->DES解密->DES解密->DES解密->P 进行解密。
DES-EDE3模式:使用 P->DES加密->DES解密->DES加密->C 进行加密,使用 C->DES解密->DES加密->DES解密->P 进行解密。
优势:
不足:
分组密码在加密时,明文分组的长度是固定的,而实际应用中待加密消息的数据量是不定的,数据格式多种多样。为了能在各类应用场合使用DES,美国在FIPS PUS 74和81中定义了DES的4种运行模式:
ECB,CBC,CFB,OFB,分组密码工做模式描述了如何重复加密比较长的多个数据块。
ECB,CBC是块模式,CFB、OFB是流模式。ECB安全性比较差,先不学了,Go的包中也没有。
CBC(Cipher Block Chaining, 密码块链)模式中每个分组要先和前一个分组加密后的数据进行异或操做,而后再进行加密。
加密:
解密:
CFB(Cipher Feedback, 密码反馈)模式和CBC模式比较类似,前一个分组的密文加密后和当前分组的明文异或操做生成当前分组的密文。
加密:
解密:
注意,解密函数与加密函数一致。
OFB(Output Feedback,输出反馈)模式与CFB模式相似,区别在于使用上一个分组的密码序列加密生成当前分组的密码序列。
总结
CTR模式在学AES时再说。
好,以上都没什么用,由于DES被破解啦!!!(看到这句话的小伙伴都快哭了)不过,增强版还能够用,接下来就说说3DES。
Des的Go实现咱们不是使用Go语言来实现Des,已经有大神写好了,咱们会调用就能够了。
des包
func NewCipher(key []byte) (cipher.Block, error)
建立并返回一个使用DES算法的cipher.Block接口。
cipher包
func NewCBCEncrypter(b Block, iv []byte) BlockMode
返回一个密码分组连接模式的、底层用b加密的BlockMode接口,初始向量iv的长度必须等于b的块尺寸。
BlockMode的方法
CryptBlocks(dst, src []byte)
加密或解密连续的数据块,src的尺寸必须是块大小的整数倍,src和dst可指向同一内存地址
func NewCBCDecrypter(b Block, iv []byte) BlockMode
返回一个密码分组连接模式的、底层用b解密的BlockMode接口,初始向量iv必须和加密时使用的iv相同。
CBC模式须要填充,解密后咱们还须要去掉填充,因为填充什么没有要求,咱们就填充缺乏的长度,这样去掉填充时就容易切片了。
func PaddingLastGroup(plainText []byte,blockSize int) []byte{ padNum := blockSize - len(plainText)%blockSize char := []byte{byte(padNum)} newPlain := bytes.Repeat(char,padNum) plainText = append(plainText,newPlain...) return plainText }
func UnpaddingLastGroup(plainText []byte) []byte { length := len(plainText) number := int(plainText[length-1]) return plainText[:length-number] }
func DesEncrypt(plainText,iv, key []byte) ([]byte,error) { if len(iv) != 8{ _, file, line, _ := runtime.Caller(0) return nil,util.Error(file,line+1,errors.IvError) } block, err :=des.NewCipher(key) if err != nil{ _, file, line, _ := runtime.Caller(0) return nil,util.Error(file,line+1,errors.DesKeyError) } // padding plainText newText := util.PaddingLastGroup(plainText,des.BlockSize) // Create a CBC interface blockMode := cipher.NewCBCEncrypter(block,iv) // use same one to save space blockMode.CryptBlocks(newText,newText) return newText,nil }
func DesDecrypt(cipherText,iv,key []byte) ([]byte,error) { if len(iv) != 8{ _, file, line, _ := runtime.Caller(0) return nil,util.Error(file,line+1,errors.IvError) } block, err :=des.NewCipher(key) if err != nil{ _, file, line, _ := runtime.Caller(0) return nil,util.Error(file,line+1,errors.DesKeyError) } // Create a CBC interface blockMode := cipher.NewCBCDecrypter(block,iv) plainText := make([]byte,len(cipherText)) blockMode.CryptBlocks(plainText,cipherText) return util.UnpaddingLastGroup(plainText),nil }
部分测试代码
iv := []byte("12345678") key := []byte("ladykill") plainText := []byte("hellocrypto") cipherText,err := DesEncrypt(plainText,iv,key) if err != nil{ fmt.Println(err) os.Exit(0) } fmt.Printf("加密后:%s\n",string(cipherText)) decryText,_ := DesDecrypt(cipherText,iv,key) fmt.Printf("解密后:%s\n",string(decryText))
3Des只须要建立时使用des.NewTripleDESCipher(key)便可。
代码我放到了gitee上:https://gitee.com/frankyu365/gocrypto
您能够查看仓库Readme文档或Go-包管理(管理工具对比及go mod的使用)来进行安装
《现代密码学教程 谷利泽,杨义先等》
Go标准库-crypto/des
Go标准库-crypto/cipher
更多Go相关内容:Go-Golang学习总结笔记
有问题请下方评论,转载请注明出处,并附有原文连接,谢谢!若有侵权,请及时联系。·