——用相同的密钥进行加密和解密
此次主要介绍比特序列运算和XOR(异或)运算。这两种运算在计算机数据处理中经常出现,因此大家应该在此属性他们。
DES(Data Encryption)是1977年美国联邦信息处理标准(FIPS)中所采用的一种对称密码(FIPS46-3)。DES一直以来被美国及其他国家的政府和银行等广泛使用。
随着计算机的进步,现在DES已经能够被暴力破解,强度大不如前了。20世纪末,RSA公司举办过破译DES密钥的比赛,我们可以看一看RSA公司官方公布的比赛结果:1997年的DES Challenge I 中用了96天破译密钥,1998年的DES Challenge II-1中用了41天,1998年的DES Challenge II-2中用了56小时,1999年的DES Challenge III 中只用了22小时15分钟。
由于DES的密文可以在短时间内被破译,因此除了用它来解密一起的密文以外,现在我们不应该再使用DES了。
DES是一种将64比特的明文加密成64比特的密文的对称密码算法,它的密钥的长度是56比特。尽管从规格上来说,DES的密钥长度是64比特,但由于每隔7比特会设置一个用于错误检查的比特,因此实质上其密钥长度是56比特。
DES 是以64比特的明文(比特序列)为一个单位来进行加密的,这个64比特的单位称为 分组 ,一般来说,以分组为单位进行处理的密码算法称为 分组密码 ,DES就是分组密码的一种。
DES每次只能加密64比特的数据,如果要加密的明文比较长,就需要对DES加密进行迭代(反复),而迭代的具体方式就称为 模式 。
DES的基本结构是由Horst Feistel设计的,因此也称为 Feistel网络(Feistel network) 、Feistel结构(Feistel structure)或者Feistel密码(Feistel cipher)。这一结构不仅被用于DES,在其他很多密码算法中也有应用。
Feistel网络中,加密的各个步骤称为轮,整个加密过程就是进行若干次轮的循环,下图,展现的是Feistel网络中一轮的计算流程。DES是一种16轮循环的Feistel网络。
但是,这样看来,“右侧”根本没有加密,因此我们需要用不同的子密钥对一轮的处理重复若干次,并在没两轮处理指间将左侧和有责的数据对调。
上图展现了一个3轮的Feistel网络,3轮加密计算需要进行两次左右对调。对调只在两轮指间进行,租后一轮结束不需要对调。
那么,Feistel网络如何解密呢?
如上图所示,通过上述操作都能够将密文正确的还原明文。
有多轮的情况也是一样的,也就是说,Feistel网络的解密操作,只要按照相反的顺序来使用子密钥就可以完成了,而Feistel网络本身的结构,在加密和解密都是完全相同的。
该系列的主要内容来自《图解密码技术第三版》
我只是知识的搬运工
文章中的插图来源于原著
加密的原因:保证数据安全
加密必备要素:1、明文/密文 2、秘钥 3、算法
秘钥:在密码学中是一个定长的字符串、需要根据加密算法确定其长度
加密算法解密算法一般互逆、也可能相同
常用的两种加密方式:
对称加密:秘钥:加密解密使用同一个密钥、数据的机密性双向保证、加密效率高、适合加密于大数据大文件、加密强度不高(相对于非对称加密)
非对称加密:秘钥:加密解密使用的不同秘钥、有两个密钥、需要使用密钥生成算法生成两个秘钥、数据的机密性只能单向加密、如果想解决这个问题、双向都需要各自有一对秘钥、加密效率低、加密强度高
公钥:可以公开出来的密钥、公钥加密私钥解密
私钥:需要自己妥善保管、不能公开、私钥加密公钥解密
安全程度高:多次加密
按位异或运算
凯撒密码:加密方式 通过将铭文所使用的字母表按照一定的字数平移来进行加密
mod:取余
加密三要素:明文/密文(字母)、秘钥(3)、算法(向右平移3/-3)
安全常识:不要使用自己研发的算法、不要钻牛角尖、没必要研究底层实现、了解怎么应用;低强度的密码比不进行任何加密更危险;任何密码都会被破解;密码只是信息安全的一部分
保证数据的机密性、完整性、认证、不可否认性
计算机操作对象不是文字、而是由0或1排列而成的比特序列、程序存储在磁盘是二进制的字符串、为比特序列、将现实的东西映射为比特序列的操作称为编码、加密又称之为编码、解密称之为解码、根据ASCII对照表找到对应的数字、转换成二进制
三种对称加密算法:DES\3DES\ AES
DES:已经被破解、除了用它来解密以前的明文、不再使用
密钥长度为56bit/8、为7byte、每隔7个bit会设置一个用于错误检查的比特、因此实际上是64bit
分组密码(以组为单位进行处理):加密时是按照一个单位进行加密(8个字节/64bit为一组)、每一组结合秘钥通过加密算法得到密文、加密后的长度不变
3DES:三重DES为了增加DES的强度、将DES重复三次所得到的一种加密算法 密钥长度24byte、分成三份 加密--解密--加密 目的:为了兼容DES、秘钥1秘钥2相同==三个秘钥相同 ---加密一次 密钥1秘钥3相同--加密三次 三个密钥不相同最好、此时解密相当于加密、中间的一次解密是为了有三个密钥相同的情况
此时的解密操作与加密操作互逆,安全、效率低
数据先解密后加密可以么?可以、解密相当于加密、加密解密说的是算法
AES:(首选推荐)底层算法为Rijndael 分组长度为128bit、密钥长度为128bit到256bit范围内就可以 但是在AES中、密钥长度只有128bit\192bit\256bit 在go提供的接口中、只能是16字节(128bit)、其他语言中秘钥可以选择
目前为止最安全的、效率高
底层算法
分组密码的模式:
按位异或、对数据进行位运算、先将数据转换成二进制、按位异或操作符^、相同为真、不同为假、非0为假 按位异或一次为加密操作、按位异或两次为解密操作:a和b按位异或一次、结果再和b按位异或
ECB : 如果明文有规律、加密后的密文有规律不安全、go里不提供该接口、明文分组分成固定大小的块、如果最后一个分组不满足分组长度、则需要补位
CBC:密码链
问题:如何对字符串进行按位异或?解决了ECB的规律可查缺点、但是他不能并行处理、最后一个明文分组也需要填充 、初始化向量长度与分组长度相同
CFB:密文反馈模式
不需要填充最后一个分组、对密文进行加密
OFB:
不需要对最后一组进行填充
CTR计数器:
不需要对最后一组进行填充、不需要初始化向量
Go中的实现
官方文档中:
在创建aes或者是des接口时都是调用如下的方法、返回的block为一个接口
func NewCipher(key [] byte ) ( cipher . Block , error )
type Block interface {
// 返回加密字节块的大小
BlockSize() int
// 加密src的第一块数据并写入dst,src和dst可指向同一内存地址
Encrypt(dst, src []byte)
// 解密src的第一块数据并写入dst,src和dst可指向同一内存地址
Decrypt(dst, src []byte)
}
Block接口代表一个使用特定密钥的底层块加/解密器。它提供了加密和解密独立数据块的能力。
Block的Encrypt/Decrypt也能进行加密、但是只能加密第一组、因为aes的密钥长度为16、所以进行操作的第一组数据长度也是16
如果分组模式选择的是cbc
func NewCBCEncrypter(b Block, iv []byte) BlockMode 加密
func NewCBCDecrypter(b Block, iv []byte) BlockMode 解密
加密解密都调用同一个方法CryptBlocks()
并且cbc分组模式都会遇到明文最后一个分组的补充、所以会用到加密字节的大小
返回一个密码分组链接模式的、底层用b加密的BlockMode接口,初始向量iv的长度必须等于b的块尺寸。iv自己定义
返回的BlockMode同样也是一个接口类型
type BlockMode interface {
// 返回加密字节块的大小
BlockSize() int
// 加密或解密连续的数据块,src的尺寸必须是块大小的整数倍,src和dst可指向同一内存地址
CryptBlocks(dst, src []byte)
}
BlockMode接口代表一个工作在块模式(如CBC、ECB等)的加/解密器
返回的BlockMode其实是一个cbc的指针类型中的b和iv
# 加密流程:
1. 创建一个底层使用des/3des/aes的密码接口 "crypto/des" func NewCipher(key []byte) (cipher.Block, error) # -- des func NewTripleDESCipher(key []byte) (cipher.Block, error) # -- 3des "crypto/aes" func NewCipher(key []byte) (cipher.Block, error) # == aes
2. 如果使用的是cbc/ecb分组模式需要对明文分组进行填充
3. 创建一个密码分组模式的接口对象 - cbc func NewCBCEncrypter(b Block, iv []byte) BlockMode # 加密 - cfb func NewCFBEncrypter(block Block, iv []byte) Stream # 加密 - ofb - ctr
4. 加密, 得到密文
流程:
填充明文:
先求出最后一组中的字节数、创建新切片、长度为新切片、值也为切片的长度、然后利用bytes.Reapet将长度换成字节切片、追加到原明文中
//明文补充
func padPlaintText(plaintText []byte,blockSize int)[]byte{
//1、求出需要填充的个数
padNum := blockSize-len(plaintText) % blockSize
//2、对填充的个数进行操作、与原明文进行合并
newPadding := []byte{byte(padNum)}
newPlain := bytes.Repeat(newPadding,padNum)
plaintText = append(plaintText,newPlain...)
return plaintText
}
去掉填充数据:
拿去切片中的最后一个字节、得到尾部填充的字节个数、截取返回
//解密后的明文曲调补充的地方
func createPlaintText(plaintText []byte,blockSize int)[]byte{
//1、得到最后一个字节、并将字节转换成数字、去掉明文中此数字大小的字节
padNum := int(plaintText[len(plaintText)-1])
newPadding := plaintText[:len(plaintText)-padNum]
return newPadding
}
des加密:
1、创建一个底层使用des的密码接口、参数为秘钥、返回一个接口
2、对明文进行填充
3、创建一个cbc模式的接口、需要创建iv初始化向量、返回一个blockmode对象
4、加密、调用blockmode中的cryptBlock函数进行加密、参数为目标参数和源参数
//des利用分组模式cbc进行加密
func EncryptoText(plaintText []byte,key []byte)[]byte{
//1、创建des对象
cipherBlock,err := des.NewCipher(key)
if err != nil {
panic(err)
}
//2、对明文进行填充
newText := padPlaintText(plaintText,cipherBlock.BlockSize())
//3、选择分组模式、其中向量的长度必须与分组长度相同
iv := make([]byte,cipherBlock.BlockSize())
blockMode := cipher.NewCBCEncrypter(cipherBlock,iv)
//4、加密
blockMode.CryptBlocks(newText,newText)
return newText
}
des解密:
1、创建一个底层使用des的密码接口、参数为秘钥、返回一个接口
2、创建一个cbc模式的接口、需要创建iv初始化向量,返回一个blockmode对象
3、加密、调用blockmode中的cryptBlock函数进行解密、参数为目标参数和源参数
4、调用去掉填充数据的方法
//des利用分组模式cbc进行解密
func DecryptoText(cipherText []byte, key []byte)[]byte{
//1、创建des对象
cipherBlock,err := des.NewCipher(key)
if err != nil {
panic(err)
}
//2、创建cbc分组模式接口
iv := []byte("12345678")
blockMode := cipher.NewCBCDecrypter(cipherBlock,iv)
//3、解密
blockMode.CryptBlocks(cipherText,cipherText)
//4、将解密后的数据进行去除填充的数据
newText := clearPlaintText(cipherText,cipherBlock.BlockSize())
return newText
}
Main函数调用
func main(){
//需要进行加密的明文
plaintText := []byte("CBC--密文没有规律、经常使用的加密方式,最后一个分组需要填充,需要初始化向量" +
"(一个数组、数组的长度与明文分组相等、数据来源:负责加密的人提供,加解密使用的初始化向量必须相同)")
//密钥Key的长度需要与分组长度相同、且加密解密的密钥相同
key := []byte("1234abcd")
//调用加密函数
cipherText := EncryptoText(plaintText,key)
newPlaintText := DecryptoText(cipherText,key)
fmt.Println(string(newPlaintText))
}
AES加密解密相同、所以只需要调用一次方法就可以加密、调用两次则解密
推荐是用分组模式:cbc、ctr
aes利用分组模式cbc进行加密
//对明文进行补充
func paddingPlaintText(plaintText []byte , blockSize int ) []byte {
//1、求出分组余数
padNum := blockSize - len(plaintText) % blockSize
//2、将余数转换为字节切片、然后利用bytes.Repeat得出有该余数的大小的字节切片
padByte := bytes.Repeat([]byte{byte(padNum)},padNum)
//3、将补充的字节切片添加到原明文中
plaintText = append(plaintText,padByte...)
return plaintText
}
//aes加密
func encryptionText(plaintText []byte, key []byte) []byte {
//1、创建aes对象
block,err := aes.NewCipher(key)
if err != nil {
panic(err)
}
//2、明文补充
newText := paddingPlaintText(plaintText,block.BlockSize())
//3、创建cbc对象
iv := []byte("12345678abcdefgh")
blockMode := cipher.NewCBCEncrypter(block,iv)
//4、加密
blockMode.CryptBlocks(newText,newText)
return newText
}
//解密后的去尾
func clearplaintText(plaintText []byte, blockSize int) []byte {
//1、得到最后一个字节、并转换成整型数据
padNum := int(plaintText[len(plaintText)-1])
//2、截取明文字节中去掉得到的整型数据之前的数据、此处出错、没有用len-padNum
newText := plaintText[:len(plaintText)-padNum]
return newText
}
//aes解密
func deCryptionText(crypherText []byte, key []byte ) []byte {
//1、创建aes对象
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
//2、创建cbc对象
iv := []byte("12345678abcdefgh")
blockMode := cipher.NewCBCDecrypter(block,iv)
//3、解密
blockMode.CryptBlocks(crypherText,crypherText)
//4、去尾
newText := clearplaintText(crypherText,block.BlockSize())
return newText
}
func main(){
//需要进行加密的明文
plaintText := []byte("CBC--密文没有规律、经常使用的加密方式,最后一个分组需要填充,需要初始化向量")
//密钥Key的长度需要与分组长度相同、且加密解密的密钥相同
key := []byte("12345678abcdefgh")
//调用加密函数
cipherText := encryptionText(plaintText,key)
//调用解密函数
newPlaintText := deCryptionText(cipherText,key)
fmt.Println("解密后",string(newPlaintText))
}
//aes--ctr加密
func encryptionCtrText(plaintText []byte, key []byte) []byte {
//1、创建aes对象
block,err := aes.NewCipher(key)
if err != nil {
panic(err)
}
//2、创建ctr对象,虽然ctr模式不需要iv,但是go中使用ctr时还是需要iv
iv := []byte("12345678abcdefgh")
stream := cipher.NewCTR(block,iv)
stream.XORKeyStream(plaintText,plaintText)
return plaintText
}
func main() {
//aes--ctr加密解密、调用两次即为解密、因为加密解密函数相同stream.XORKeyStream
ctrcipherText := encryptionCtrText(plaintText, key)
ctrPlaintText := encryptionCtrText(ctrcipherText,key)
fmt.Println("aes解密后", string(ctrPlaintText))
}
英文单词:
明文:plaintext 密文:ciphertext 填充:padding/fill 去掉clear 加密Encryption 解密Decryption
des对称加密,是一种比较传统的加密方式,其加密运算、解密运算使用的是同样的密钥,信息的发送者和信息的接收者在进行信息的传输与处理时,必须共同持有该密码(称为对称密码),是一种对称加密算法。
DES全称Data Encryption Standard,是一种使用密匙加密的块算法。现在认为是一种不安全的加密算法,因为现在已经有用穷举法攻破DES密码的报道了。尽管如此,该加密算法还是运用非常普遍,是一种标准的加密算法。3DES是DES的加强版本。
DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位,产生最大 64 位的分组大小。这是一个迭代的分组密码,使用称为 Feistel 的技术,其中将加密的文本块分成两半。使用子密钥对其中一半应用循环功能,然后将输出与另一半进行“异或”运算;接着交换这两半,这一过程会继续下去,但最后一个循环不交换。DES 使用 16 个循环,使用异或,置换,代换,移位操作四种基本运算。
网络安全通信中要用到两类密码算法,一类是对称密码算法,另一类是非对称密码算法。对称密码算法有时又叫传统密码算法、秘密密钥算法或单密钥算法,非对称密码算法也叫公开密钥密码算法或双密钥算法。对称密码算法的加密密钥能够从解密密钥中推算出来,反过来也成立。在大多数对称算法中,加密解密密钥是相同的。它要求发送者和接收者在安全通信之前,商定一个密钥。对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人都能对消息进行加密解密。只要通信需要保密,密钥就必须保密。
对称算法又可分为两类。一次只对明文中的单个位(有时对字节)运算的算法称为序列算法或序列密码。另一类算法是对明文的一组位进行运算,这些位组称为分组,相应的算法称为分组算法或分组密码。现代计算机密码算法的典型分组长度为64位――这个长度既考虑到分析破译密码的难度,又考虑到使用的方便性。后来,随着破译能力的发展,分组长度又提高到128位或更长。
常用的采用对称密码术的加密方案有5个组成部分(如图所示)
1)明文:原始信息。
2)加密算法:以密钥为参数,对明文进行多种置换和转换的规则和步骤,变换结果为密文。
3)密钥:加密与解密算法的参数,直接影响对明文进行变换的结果。
4)密文:对明文进行变换的结果。
5)解密算法:加密算法的逆变换,以密文为输入、密钥为参数,变换结果为明文。
对称密码当中有几种常用到的数学运算。这些运算的共同目的就是把被加密的明文数码尽可能深地打乱,从而加大破译的难度。
◆移位和循环移位
移位就是将一段数码按照规定的位数整体性地左移或右移。循环右移就是当右移时,把数码的最后的位移到数码的最前头,循环左移正相反。例如,对十进制数码12345678循环右移1位(十进制位)的结果为81234567,而循环左移1位的结果则为23456781。
◆置换
就是将数码中的某一位的值根据置换表的规定,用另一位代替。它不像移位操作那样整齐有序,看上去杂乱无章。这正是加密所需,被经常应用。
◆扩展
就是将一段数码扩展成比原来位数更长的数码。扩展方法有多种,例如,可以用置换的方法,以扩展置换表来规定扩展后的数码每一位的替代值。
◆压缩
就是将一段数码压缩成比原来位数更短的数码。压缩方法有多种,例如,也可以用置换的方法,以表来规定压缩后的数码每一位的替代值。
◆异或
这是一种二进制布尔代数运算。异或的数学符号为⊕ ,它的运算法则如下:
1⊕1 = 0
0⊕0 = 0
1⊕0 = 1
0⊕1 = 1
也可以简单地理解为,参与异或运算的两数位如相等,则结果为0,不等则为1。
◆迭代
迭代就是多次重复相同的运算,这在密码算法中经常使用,以使得形成的密文更加难以破解。
下面我们将介绍一种流行的对称密码算法DES。
DES是Data Encryption Standard(数据加密标准)的缩写。它是由IBM公司研制的一种对称密码算法,美国国家标准局于1977年公布把它作为非机要部门使用的数据加密标准,三十年来,它一直活跃在国际保密通信的舞台上,扮演了十分重要的角色。
DES是一个分组加密算法,典型的DES以64位为分组对数据加密,加密和解密用的是同一个算法。它的密钥长度是56位(因为每个第8 位都用作奇偶校验),密钥可以是任意的56位的数,而且可以任意时候改变。其中有极少数被认为是易破解的弱密钥,但是很容易避开它们不用。所以保密性依赖于密钥。
DES加密的算法框架如下:
首先要生成一套加密密钥,从用户处取得一个64位长的密码口令,然后通过等分、移位、选取和迭代形成一套16个加密密钥,分别供每一轮运算中使用。
DES对64位(bit)的明文分组M进行操作,M经过一个初始置换IP,置换成m0。将m0明文分成左半部分和右半部分m0 = (L0,R0),各32位长。然后进行16轮完全相同的运算(迭代),这些运算被称为函数f,在每一轮运算过程中数据与相应的密钥结合。
在每一轮中,密钥位移位,然后再从密钥的56位中选出48位。通过一个扩展置换将数据的右半部分扩展成48位,并通过一个异或操作替代成新的48位数据,再将其压缩置换成32位。这四步运算构成了函数f。然后,通过另一个异或运算,函数f的输出与左半部分结合,其结果成为新的右半部分,原来的右半部分成为新的左半部分。将该操作重复16次。
经过16轮迭代后,左,右半部分合在一起经过一个末置换(数据整理),这样就完成了加密过程。
加密流程如图所示。
DES解密过程:
在了解了加密过程中所有的代替、置换、异或和循环迭代之后,读者也许会认为,解密算法应该是加密的逆运算,与加密算法完全不同。恰恰相反,经过密码学家精心设计选择的各种操作,DES获得了一个非常有用的性质:加密和解密使用相同的算法!
DES加密和解密唯一的不同是密钥的次序相反。如果各轮加密密钥分别是K1,K2,K3…K16,那么解密密钥就是K16,K15,K14…K1。这也就是DES被称为对称算法的理由吧。
至于对称密码为什么能对称? DES具体是如何操作的?本文附录中将做进一步介绍,有兴趣的读者不妨去读一读探个究竟
4.DES算法的安全性和发展
DES的安全性首先取决于密钥的长度。密钥越长,破译者利用穷举法搜索密钥的难度就越大。目前,根据当今计算机的处理速度和能力,56位长度的密钥已经能够被破解,而128位的密钥则被认为是安全的,但随着时间的推移,这个数字也迟早会被突破。
另外,对DES算法进行某种变型和改进也是提高DES算法安全性的途径。
例如后来演变出的3-DES算法使用了3个独立密钥进行三重DES加密,这就比DES大大提高了安全性。如果56位DES用穷举搜索来破译需要2∧56次运算,而3-DES 则需要2∧112次。
又如,独立子密钥DES由于每轮都使用不同的子密钥,这意味着其密钥长度在56位的基础上扩大到768位。DES还有DESX、CRYPT、GDES、RDES等变型。这些变型和改进的目的都是为了加大破译难度以及提高密码运算的效率
DES (Data Encryption Standard)是分组对称密码算法。
DES算法利用 多次组合替代算法 和 换位算法 ,分散和错乱的相互作用,把明文编制成密码强度很高的密文,它的加密和解密用的是同一算法。
DES算法,是一种 乘积密码 ,其在算法结构上主要采用了 置换 、 代替 、 模二相加 等函数,通过 轮函数 迭代的方式来进行计算和工作。
DES算法也会使用到数据置换技术,主要有初始置换 IP 和逆初始置换 IP^-1 两种类型。DES算法使用置换运算的目的是将原始明文的所有格式及所有数据全部打乱重排。而在轮加密函数中,即将数据全部打乱重排,同时在数据格式方面,将原有的32位数据格式,扩展成为48位数据格式,目的是为了满足S盒组对数据长度和数据格式规范的要求。
一组数据信息经过一系列的非线性变换以后,很难从中推导出其计算的过程和使用的非线性组合;但是如果这组数据信息使用的是线性变换,计算就容易的多。在DES算法中,属于非线性变换的计算过程只有S盒,其余的数据计算和变换都是属于线性变换,所以DES算法安全的关键在于S盒的安全强度。此外,S盒和置换IP相互配合,形成了很强的抗差分攻击和抗线性攻击能力,其中抗差分攻击能力更强一些。
DES算法是一种分组加密机制,将明文分成N个组,然后对各个组进行加密,形成各自的密文,最后把所有的分组密文进行合并,形成最终的密文。
DES加密是对每个分组进行加密,所以输入的参数为分组明文和密钥,明文分组需要置换和迭代,密钥也需要置换和循环移位。在初始置换IP中,根据一张8*8的置换表,将64位的明文打乱、打杂,从而提高加密的强度;再经过16次的迭代运算,在这些迭代运算中,要运用到子密钥;每组形成的初始密文,再次经过初始逆置换 IP^-1 ,它是初始置换的逆运算,最后得到分组的最终密文。
图2右半部分,给出了作用56比特密钥的过程。DES算法的加密密钥是64比特,但是由于密钥的第n*8(n=1,2…8)是校验(保证含有奇数个1),因此实际参与加密的的密钥只有 56比特 。开始时,密钥经过一个置换,然后经过循环左移和另一个置换分别得到子密钥ki,供每一轮的迭代加密使用。每轮的置换函数都一样,但是由于密钥位的重复迭代使得子密钥互不相同。
DES算法 利用多次组合替代算法和换位算法,分散和错乱的相互作用,把明文编制成密码强度很高的密文,它的加密和解密用的是同一算法。
DES算法详述:DES对64位明文分组(密钥56bit)进行操作。
1、 初始置换函数IP:64位明文分组x经过一个初始置换函数IP,产生64位的输出x0,再将分组x0分成左半部分L0和右半部分R0:即将输入的第58位换到第一位,第50位换到第2位,…,依次类推,最后一位是原来的第7位。L0、R0则是换位输出后的两部分,L0是输出的左32位,R0是右32位。例,设置换前的输入值为D1D2D3…D64,则经过初始置换后的结果为:L0=D58D50…D8;R0=D57D49…D7.其置换规则如表1所示。
DES加密过程最后的逆置换 IP^-1 ,是表1的 逆过程 。就是把原来的每一位都恢复过去,即把第1位的数据,放回到第58位,把第2位的数据,放回到第50位。
2、 获取子密钥 Ki :DES加密算法的密钥长度为56位,一般表示为64位(每个第8位用于奇偶校验),将用户提供的64位初始密钥经过一系列的处理得到K1,K2,…,K16,分别作为 1~16 轮运算的 16个子密钥 。
(1). 将64位密钥去掉8个校验位,用密钥置换 PC-1 (表2)置换剩下的56位密钥;
(2). 将56位分成前28位C0和后28位D0,即 PC-1(K56)=C0D0 ;
(3). 根据轮数,这两部分分别循环左移1位或2位,表3:
(4). 移动后,将两部分合并成56位后通过压缩置换PC-2(表4)后得到48位子密钥,即Ki=PC-2(CiDi).
子密钥产生如图2所示:
3、 密码函数F(非线性的)
(1). 函数F的操作步骤:密码函数F 的输入是32比特数据和48比特的子密钥:
A.扩展置换(E):将数据的右半部分Ri从32位扩展为48位。位选择函数(也称E盒),如表5所示:
B.异或:扩展后的48位输出E(Ri)与压缩后的48位密钥Ki作异或运算;
C.S盒替代:将异或得到的48位结果分成八个6位的块,每一块通过对应的一个S盒产生一个4位的输出。
(2)、D、P盒置换:将八个S盒的输出连在一起生成一个32位的输出,输出结果再通过置换P产生一个32位的输出即:F(Ri,Ki),F(Ri,Ki)算法描述如图3,最后,将P盒置换的结果与最初的64位分组的左半部分异或,然后,左、右半部分交换,开始下一轮计算。
4、密文输出:经过16次迭代运算后,得到L16、R16,将此作为输入,进行逆置换,即得到密文输出。逆置换正好是初始置的逆运算。例如,第1位经过初始置换后,处于第40位,而通过逆置换,又将第40位换回到第1位,其逆置换规则如表8所示:
图4为DES算法加密原理图:
DES算法加密和解密过程采用相同的算法,并采用相同的加密密钥和解密密钥,两者的区别是:(1)、DES加密是从L0、R0到L15、R15进行变换,而解密时是从L15、R15到L0、R0进行变换的;(2)、加密时各轮的加密密钥为K0K1…K15,而解密时各轮的解密密钥为K15K14…K0;(3)、加密时密钥循环左移,解密时密钥循环右移。
DES加密过程分析:
(1)、首先要生成64位密钥,这64位的密钥经过“子密钥算法”换转后,将得到总共16个子密钥。将这些子密钥标识为Kn(n=1,2,…,16)。这些子密钥主要用于总共十六次的加密迭代过程中的加密工具。
(2)、其次要将明文信息按64位数据格式为一组,对所有明文信息进行分组处理。每一段的64位明文都要经过初试置换IP,置换的目的是将数据信息全部打乱重排。然后将打乱的数据分为左右两块,左边一块共32位为一组,标识为L0;右边一块也是32位为一组,标识为R0.
(3)、置换后的数据块总共要进行总共十六次的加密迭代过程。加密迭代主要由加密函数f来实现。首先使用子密钥K1对右边32位的R0进行加密处理,得到的结果也是32位的;然后再将这个32位的结果数据与左边32位的L0进行模2处理,从而再次得到一个32位的数据组。我们将最终得到的这个32位组数据,作为第二次加密迭代的L1,往后的每一次迭代过程都与上述过程相同。
(4)、在结束了最后一轮加密迭代之后,会产生一个64位的数据信息组,然后我们将这个64位数据信息组按原有的数据排列顺序平均分为左右两等分,然后将左右两等分的部分进行位置调换,即原来左等分的数据整体位移至右侧,而原来右等分的数据则整体位移至左侧,这样经过合并后的数据将再次经过逆初始置换IP^-1的计算,我们最终将得到一组64位的密文。
DES解密过程分析:DES的解密过程与它的加密过程是一样的,这是由于DES算法本身属于对称密码体制算法,其加密和解密的过程可以共用同一个过程和运算。
DES加密函数f:在DES算法中,要将64位的明文顺利加密输出成64位的密文,而完成这项任务的核心部分就是加密函数f。加密函数f的主要作用是在第m次的加密迭代中使用子密钥Km对Km-1进行加密操作。加密函数f在加密过程中总共需要运行16轮。
十六轮迭代算法:它先将经过置换后的明文分成两组,每组32位;同时密钥也被分成了两组,每组28位,两组密钥经过运算,再联合成一个48位的密钥,参与到明文加密的运算当中。S盒子,它由8个4*16的矩阵构成,每一行放着0到15的数据,顺序各个不同,是由IBM公司设计好的。经过异或运算的明文,是一个48位的数据,在送入到S盒子的时候,被分成了8份,每份6位,每一份经过一个S盒子,经过运算后输出为4位,即是一个0到15的数字的二进制表示形式。具体运算过程为,将输入的6位中的第1位为第6位合并成一个二进制数,表示行号,其余4位也合并成一个二进制数,表示列号。在当前S盒子中,以这个行号和列号为准,取出相应的数,并以二进制的形式表示,输出,即得到4位的输出,8个S盒子共计32位。
DES算法优缺点:
(1)、产生密钥简单,但密钥必须高度保密,因而难以做到一次一密;
(2)、DES的安全性依赖于密钥的保密。攻击破解DES算法的一个主要方法是通过密钥搜索,使用运算速度非常高的计算机通过排列组合枚举的方式不断尝试各种可能的密钥,直到破解为止。一般,DES算法使用56位长的密钥,通过简单计算可知所有可能的密钥数量最多是2^56个。随着巨型计算机运算速度的不断提高,DES算法的安全性也将随之下降,然而在一般的民用商业场合,DES的安全性仍是足够可信赖的。
(3)、DES算法加密解密速度比较快,密钥比较短,加密效率很高但通信双方都要保持密钥的秘密性,为了安全还需要经常更换DES密钥。
参考链接 :