密码学之对称加密算法:DES
DES(Data Encryption Standard)是数据加密标准的简称。DES起源于20世纪70年代初IBM研制出的LUCIFER算法,LUCIFER是一种Feistel分组密码,分组长度为64比特,密钥长度为128比特。1973年 5月和1974年 8月美国国家标准局NBS(National Bureau of Standards)两次发布通告,向社会征集密码算法。结果IBM的LUCIFER算法被选中,1977年被正式公布为数据加密标准DES。
1、DES数学原理
DES算法具有严格的Feistel结构,共使用16轮替代盒置换。DES加密过程分为两条主线:明文分组加密和生成子密钥。
DES加密流程如下图所示。

DES加密过程主要分为三个阶段:
- 初始置换:按照IP表将明文分组的64位二进制数重新排列,产生新的64位输出。分为左右两部分,每部分32位,参与下面的运算。
- 16轮迭代:循环次数16次,每轮循环使用一个48位的子密钥(由子密钥生成算法产生)。迭代时DES加密的核心部分。
- 逆初始置换:将16轮迭代后的左右两部分数据合并位新的64位输出。再按照IP逆置换表进行逆初始置换,将64位二进制数重新排列,产生64位输出即加密密文。
1.1 初始IP置换
初始置换的功能是把输入的64位数据块(填充对齐之后的数据)按照下面的IP置换表进行重新组合,并把输出分为L0、R0两部分,每部分长度32位。
具体原理:根据IP置换表,将原来第58位放到第一位,第50位放到第二位,以此类推。

1.2 子密钥生成
子密钥生成流程:

具体为:
1、初始密钥为64bit,使用PC-1进行置换,去除8位校验位,剩余56bit
2、56bit密钥分位两组,每组28bit
3、两组按照密钥循环左移表进行移位操作。循环左移的位数与当前循环的轮数相关,如:第一轮左移位,第二轮左移一位。第三轮左移2位....
4、移位后合并两个28bit的分组,形成一个56bit新的分组
5、新的56bit的分组按照置换表PC-2进行置换,输出48bit的子密钥,参与后续16轮迭代运算
1.3 16轮迭代
参与迭代的元素:
- 64位输入经过初始IP置换后形成两组32位分组,分别记为Li、Ri(其中Li=Ri, Ri和子密钥进行E盒扩展、S盒压缩、P盒置换、与Li进行异或等操作)
- 由子密钥生成算法生成的48位子密钥
E盒扩展(32->48)
功能:将32位输入(R0部分)扩展为48位输出。因为64位数据分成两组,每组是32位,其中Ri要与48位的密钥进行运算。具体为:按照下面的表进行替换。
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
实质是:将32bit扩展到48bit,先将32bit的字符分为8组,每一组的前后,分别添加上一个字符和下一个字符。
S盒压缩处理(48->32)
功能:首先,将扩展的48位明文和48位密钥进行异或运算,再使用8个S盒压缩得到32位数据。
S盒就是一个4行16列的表,盒中的每一项都是一个4位二进制数表示的十进制数。输入的高低两位做为行数H,中间四位做为列数L,在S-BOX中查找第H行L列对应的数据。S盒的行列计数都是从0开始。
具体为: 将48位输入等分为8块,每块6bit。 其中取高1一个字节和低一个字节组成行号(有0、1、2、3四种),取每组中间4位组成列号,总共16种,然后根据行号和列号在8个盒中查找替换,每组由6位压缩为4位, 最后输出32位分组。

S盒是唯一的非线性变换(非数学变换),是DES中轮函数的核心,S盒的好坏决定了该算法的质量。
P盒置换(32->32)
将由S盒运算后的32位bit利用P盒在进行置换。P盒置换表满足分组扩散与混乱原则。

1.4 IP 逆置换
IP逆置换就是将16轮迭代运算后的L16和R16合并,形成新的64位分组。然后按照IP逆置换表进行替换,最后输出加密后的64位密文。

2、Go语言实践
package descrypto
import (
"bytes"
"crypto/cipher"
"crypto/des"
"fmt"
)
//DES加密
func EnCrypto(orignData, key []byte) ([]byte, error) {
block, err := des.NewCipher(key) //创建block对象
if err != nil {
return nil, err
}
PadData := PKCS5Padding(orignData, block.BlockSize()) //分组、填充
blockMole := cipher.NewCBCEncrypter(block, key) //设置加密模式CBC
encrypto := make([]byte, len(PadData)) //接受加密数据的变量
blockMole.CryptBlocks(encrypto, PadData) //加密数据
return encrypto, nil
}
//DES解密
func DeCrypto(enData, key []byte) ([]byte, error) {
block, err := des.NewCipher(key)
if err != nil {
return nil, err
}
blockModel := cipher.NewCBCDecrypter(block, key)
decrypro := make([]byte, len(enData))
blockModel.CryptBlocks(decrypro, enData) //第一个参数是接受,第二个参数是输入加密数据
decrypro = PKCS5UnPadding(decrypro) //去掉填充
return decrypro, nil
}
func PKCS5Padding(cipherText []byte, bloxkSize int) []byte {
padding := bloxkSize - len(cipherText)%bloxkSize //当分组大小正好是blockSize的整数倍时,也会填充一个分组大小
padText := bytes.Repeat([]byte{byte(padding)}, padding) //用补充字节数对应的字符进行填充,此处为5
fmt.Println(append(cipherText, padText...))
return append(cipherText, padText...)
}
func PKCS5UnPadding(cipherText []byte) []byte {
length := len(cipherText)
unpadding := int(cipherText[length-1])
return cipherText[:(length - unpadding)]
}
测试程序
package main
import (
mydes "cryptodes/descrypto"
"fmt"
"os"
)
func main() {
input := []byte("jiesjfhduefhuhgiesg")
key := []byte("acdbghuj")
fmt.Printf("Original Data: %s\n", input)
fmt.Printf("Original Data: %x\n", input)
endata, err := mydes.EnCrypto(input, key)
if err != nil {
fmt.Println("Encrypto Data error")
os.Exit(-1)
}
fmt.Printf("Encrypto Data: %x\n", endata)
dedata, err := mydes.DeCrypto(endata, key)
if err != nil {
fmt.Println("Decrypto Data Error")
os.Exit(-1)
}
fmt.Printf("Decrypro Data: %x\n", dedata)
}
-------------------测试结果---------------------
> go run .\TestDes.go
Original Data: jiesjfhduefhuhgiesg
Original Data: 6a6965736a6668647565666875686769657367
[106 105 101 115 106 102 104 100 117 101 102 104 117 104 103 105 101 115 103 5 5 5 5 5] //使用5填充
Encrypto Data: ea408f670b0abd0c906c7b53bd0abec406e6a700b58cb4ef
Decrypro Data: 6a6965736a6668647565666875686769657367
3、3DSE算法
3.1算法原理
双重DES
利用两个不同的密钥对明文进行两次连续加密。

三重DES
3DES(或称为 Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称。它相当于是对每个数据块应用三次 DES 加密算法。由于计算机运算能力的增强,原版 DES 密码的密钥长度变得容易被暴力破解;

目前双密钥三重DES加密有两种方案:DES-EEE2和DES-EDE2。3DES 即是设计用来提供一种相对简单的方法,即通过增加 DES 的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。
注意:3DES 的密钥长度必须是24个字节。3DES算法将24字节密钥以8字节长度进行了分组,前八字节为KEY1,中间8字节为KEY2,最后8字节为KEY3。
3.2 Go语言实践
3DES加解密代码(Go语言)
func TripDesEncrypro(data, key []byte) ([]byte, error) {
block, err := des.NewTripleDESCipher(key)
if err != nil {
return nil, err
}
originalData := PKCS5Padding(data, block.BlockSize())
blockModel := cipher.NewCBCEncrypter(block, key[:8])
encrypto := make([]byte, len(originalData))
blockModel.CryptBlocks(encrypto, originalData)
return encrypto, nil
}
func TripDesDecrypro(data, key []byte) ([]byte, error) {
block, err := des.NewTripleDESCipher(key)
if err != nil {
return nil, err
}
blockModel := cipher.NewCBCDecrypter(block, key[:8])
decrypto := make([]byte, len(data))
blockModel.CryptBlocks(decrypto, data)
decrypto = PKCS5UnPadding(decrypto)
return decrypto, nil
}
4、DES算法的安全性
DES实际密钥长度是56bit。就目前计算机计算能力而言,DES已不能抵抗对密钥的穷举搜索攻击。1991年1月,电子边境基金会EFF通过互联网上的10万台计算机合作,仅用22小时15分就破解了56-bit的DES算法。
DES算法的脆弱性主要体现在以下两部分:
-
密钥容量:56位不太可能提供足够的安全性
-
S盒:设计原理至今未公布,可能隐含有陷阱。

浙公网安备 33010602011771号