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轮循环。
单轮加密
- 子密钥:中间的“子密钥”指的是本轮加密所使用的的密钥,在Feistel网络中,每一轮都需要使用一个不同的子密钥。由于密钥只在一轮中使用,它只是一个局部的密钥,因此才称为子密钥(subkey)。
- 轮函数:根据“右侧”和子密钥生成对“左侧”进行加密的比特序列,它是密码系统核心。将轮函数的输出与“左侧”进行XOR运算,其结果就是“加密后的左侧”。也就是说,我们用XOR将轮函数的输出与“左侧”进行合并。而输入的“右侧”则会直接成为输出的“右侧”。
两轮加密
连续两轮加密的密钥如果相同,相当于加密之后又进行解密。
三轮加密
三轮解密
部分实际上没有进行任何处理,在加密算法中看起来是一种浪费,却保证了可解密性,因为完全没有进行任何处理的右半部分是解密过程所必须的信息。
由于加密和解密可以用完全相同的结构来实现,因此用于实现 DES 算法的硬件设备的设计也变得更容易了。
三重DES
三重DES(triple-des)是为了增加DES的强度,将DES重复3次所得到的一种密码算法,也称为TDEA(Triple Date Encryption Algorithm),通常缩写为3DES。
明文经过三次DES处理才能变成最后的密文,由于DES密钥的长度实质上是56比特,因此三重DES的密钥长度就是56×3=168比特。
从图中我们可以发现,三重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
}