| … | … |
由于初始置换是公开的,没有密码意义。有很多DES实现都去除了,有人认为是当时为了更好放到DES芯片中。
Feistel结构
一轮迭代
按下述规则进行16次迭代,1≤i≤16
轮函数F
F(,)以长度为32比特串作为第一输入,以长度为48比特串作为第二个输入,产生长度为32比特的输出。
E扩展
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扩展和进行异或
S盒代换
使用8个S盒S1……S8,每个Si是一个固定的4*16阶矩阵,其元素取0~15之间的整数。
给定长度为6的比特串,如Bj=b1b2b3b4b5b6,Sj(Bj)计算如下:
- b1b6两个比特确定了Sj的行r的二进制表示(0≤r≤3),
- b2b3b4b5四个比特确定了Sj的列c的二进制表示(0≤c≤15),
- Sj(Bj)定义成长度为4的比特串的值Sj(r,c)。由此可以算出Cj=Sj(Bj),1≤j≤8。
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
- b1b6为11,r=3
- b2b3b4b5为1001,c=9
- S1(3,9)为11,二进制为1011,Cj就是11了,即用1011替换了110011。
P置换
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相同,这里就不粘贴了,不然文章太长了。
3Des
3DES,顾名思义,使用三次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 进行解密。
优缺点
优点:
- 密钥长度增加到112位或168位,克服了DES面临的穷举攻击。
- 相对于DES,增强了算法复杂度,提高了安全性。
- 由于DES已经大规模使用,升级到3DES比更新新算法成本小得多。
- DES比其它任何加密算法受到的分析时间都长的多,相应地,3DES抗分析能力更强。
不足:
- 3DES加解速度较慢。
- 虽然密钥长度增加了,但明文分组长度没变,与密钥长度的增长不匹配。
分组模式
分组密码在加密时,明文分组的长度是固定的,而实际应用中待加密消息的数据量是不定的,数据格式多种多样。为了能在各种应用场合使用DES,美国在FIPS PUS 74和81中定义了DES的4种运行模式:
ECB,CBC,CFB,OFB,分组密码工作模式描述了如何重复加密比较长的多个数据块。
ECB,CBC是块模式,CFB、OFB是流模式。ECB安全性比较差,先不学了,Go的包中也没有。
CBC
CBC(Cipher Block Chaining, 密码块链)模式中每一个分组要先和前一个分组加密后的数据进行异或操作,然后再进行加密。
加密:
解密:
- IV:initialization vector,初始向量,
- 将长消息分块,若最后一个分块不足分组长度,则需要填充
- 加密和解密过程分别调用加密算法和解密算法
- 存在密文扩展(明文填充带来的扩展和IV传输的扩展)
- 密文块需按顺序逐一解密
- 存在错误传播(只传播下一块密文)
- 适合大于一个分组长度的长数据加密
CFB
CFB(Cipher Feedback, 密码反馈)模式和CBC模式比较相似,前一个分组的密文加密后和当前分组的明文异或操作生成当前分组的密文。
加密:
解密:
注意,解密函数与加密函数一致。
- 消息作为比特流进行加密,无须分组填充
- 加密和解密过程只调用加密算法
- 存在密文扩展(IV传输的扩展)
- 密文块需按顺序逐一解密
- 存在错误传播(只传播后面的几块)
- 适合大于一个分组长度的长数据加密
- 可用于自同步序列密码
OFB
OFB(Output Feedback,输出反馈)模式与CFB模式类似,区别在于使用上一个分组的密码序列加密生成当前分组的密码序列。
总结
- ECB是最快、最简单的分组密码模式,但它的安全性最弱,一般不推荐使用ECB加密消息,但如果是加密随机数据,如密钥,ECB则是最好的选择。
- CBC适合文件加密,而且有少量错误时不会造成同步失败,是软件加密的最好选择。
- CFB通常是加密分组序列所选择的模式,它也能容忍少量错误扩展,且具有同步恢复功能。推荐使用CTR模式代替。
- OFB是在极易出错的环境中选用的模式,但需有高速同步机制。推荐使用CTR模式代替。
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]
}
加密
- 使用des.NewCipher获取块
- 填充明文
- 使用cipher.NewCBCEncrypter生成CBC模式块
- 使用模式块的CryptBlocks进行加密,由于可指向同一内存地址,我们仍使用同一变量,节省内存
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
}
解密
- 使用des.NewCipher获取块
- 使用cipher.NewCBCDecrypter生成CBC模式块
- 使用模式块的CryptBlocks进行解密
- 去掉明文填充
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))
结果截图
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
朋友。**
[外链图片转存中…(img-AEeYAamL-1715488483332)]
[外链图片转存中…(img-pxPTs7y9-1715488483332)]
[外链图片转存中…(img-Em22N3SQ-1715488483333)]
[外链图片转存中…(img-hAcND5bU-1715488483333)]
[外链图片转存中…(img-4KSQp1kR-1715488483333)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!