密码学之对称加密算法: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盒:设计原理至今未公布,可能隐含有陷阱。

posted @ 2022-12-05 17:07  丘山996  阅读(627)  评论(0)    收藏  举报