DES
  • DES(Data Encryption)是1977年美国联邦信息处理标准(FIPS)中所采用的一种对称密码(FIPS46-3),一直以来被美国及其他国家的政府和银行等广泛使用。随着计算机的进步,DES已经能够被暴力破解,1997年的DES Challenge I 中用了96天破译密钥,1998年的DES Challenge II-1中用了41天,1998年的DES Challenge II-2中用了56小时,1999年的DES Challenge III 中只用了22小时15分钟。
  • DES是一种将64比特的明文加密成64比特的密文的对称密码算法,它的密钥的长度是56比特。尽管从规格上来说,DES的密钥长度是64比特,但由于每隔7比特会设置一个用于错误检查的比特,因此实质上其密钥长度是56比特。
  • DES 是以64比特的明文(比特序列)为一个单位来进行加密的,这个64比特的单位称为分组 ,一般来说,以分组为单位进行处理的密码算法称为分组密码,DES就是分组密码的一种。
  • DES每次只能加密64比特的数据,如果要加密的明文比较长,就需要对DES加密进行迭代(反复),而迭代的具体方式就称为模式。
  • DES 内部实现理论:在 des 中各个步骤称为轮,整个加密过程进行16轮循环。
golang实现三重DES加密解密_go单轮加密 golang实现三重DES加密解密_密钥长度_02
  • 子密钥:中间的“子密钥”指的是本轮加密所使用的的密钥,在Feistel网络中,每一轮都需要使用一个不同的子密钥。由于密钥只在一轮中使用,它只是一个局部的密钥,因此才称为子密钥(subkey)。
  • 轮函数:根据“右侧”和子密钥生成对“左侧”进行加密的比特序列,它是密码系统核心。将轮函数的输出与“左侧”进行XOR运算,其结果就是“加密后的左侧”。也就是说,我们用XOR将轮函数的输出与“左侧”进行合并。而输入的“右侧”则会直接成为输出的“右侧”。
两轮加密

连续两轮加密的密钥如果相同,相当于加密之后又进行解密。
golang实现三重DES加密解密_go_03

三轮加密 golang实现三重DES加密解密_迭代_04三轮解密 golang实现三重DES加密解密_对称密码_05

部分实际上没有进行任何处理,在加密算法中看起来是一种浪费,却保证了可解密性,因为完全没有进行任何处理的右半部分是解密过程所必须的信息。

由于加密和解密可以用完全相同的结构来实现,因此用于实现 DES 算法的硬件设备的设计也变得更容易了。

三重DES

三重DES(triple-des)是为了增加DES的强度,将DES重复3次所得到的一种密码算法,也称为TDEA(Triple Date Encryption Algorithm),通常缩写为3DES。

明文经过三次DES处理才能变成最后的密文,由于DES密钥的长度实质上是56比特,因此三重DES的密钥长度就是56×3=168比特。

golang实现三重DES加密解密_go_06

从图中我们可以发现,三重DES并不是进行三次DES加密(加密→加密→加密),而是加密→解密→加密的过程。在加密算法中加入解密操作让人感觉很不可思议,实际上这个方法是IBM公司设计出来的,目的是为了让三重DES能够兼容普通的DES。

当三重DES中所有的密钥都相同时,三重DES也就等同于普通的DES了。这是因为在前两步加密→解密之后,得到的就是最初的明文。因此,以前用DES加密的密文,就可以通过这种方式用三重DES来进行解密。也就是说,三重DES对DES具备向下兼容性。

在DES的部分我们已经提到过,DES的加密和解密过程只是改变了子密钥的顺序,而实际进行的处理是相同的。

如果所有密钥都使用相同的比特序列,则其结果与普通的DES是等价的。

如果密钥1和密钥3使用相同的密钥,而密钥2使用不同的密钥(也就是只使用两个DES密钥),这种三重DES就称为DES-EDE2。EDE表示的是加密(Encryption)→解密(Decryption)→加密(Encryption)这个流程。

密钥1、密钥2、密钥3全部使用不同的比特序列的三重DES称为des-ede3。

go 实现三重DES加密解密

在这里,我们用了一个 go 的加解密包,做了以下封装:

package main

import (
	"encoding/base64"
	"github.com/wumansgy/goEncrypt"
)

// 密钥 24字节
const secretKey = "hjdo843k920s6um4kk8sk3s8"

// 三重DES加密
func TripleDesEncrypt(encryptedString string) (string, error) {
	cryptText, err := goEncrypt.TripleDesEncrypt([]byte(encryptedString), []byte(secretKey))
	if err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(cryptText), nil
}

// 三重DES解密
func TripleDesDecrypt(decryptString string) (string, error) {
	decryptBytes, err := base64.StdEncoding.DecodeString(decryptString)
	if err != nil {
		return "", err
	}
	cryptText, err := goEncrypt.TripleDesDecrypt(decryptBytes, []byte(secretKey))
	if err != nil {
		return "", err
	}

	return string(cryptText), nil
}