DES加密算法
一、对称加密算法
网络安全通信中要用到两类密码算法,一类是对称密码算法,另一类是非对称密码算法。对称密码算法有时又叫传统密码算法、秘***算法或单**算法,非对称密码算法也叫公开**密码算法或双**算法。
对称加密的加***能够从解***中推算出来,同时解***也可以从加***中推算出来。而在大多数的对称算法中,加***和解***是相同的,所以也称这种加密算法为秘***算法或单**算法。它要求发送方和接收方在安全通信之前,商定一个**。对称算法的安全性依赖于**,泄漏**就意味着任何人都可以对他们发送或接收的消息解密,所以**的保密性对通信的安全性至关重要。
对称算法又可分为两类。一次只对明文中的单个位(有时对字节)运算的算法称为序列算法或序列密码。另一类算法是对明文的一组位进行运算,这些位组称为分组,相应的算法称为分组算法或分组密码。现代计算机密码算法的典型分组长度为64位――这个长度既考虑到分析破译密码的难度,又考虑到使用的方便性。后来,随着破译能力的发展,分组长度又提高到128位或更长。
在对称加密算法中,加密算法一般如下所示:
明文:待需要加密的原始文件
**:加密所需要的key值
加密算法:以**为参数,对明文进行多种置换和转换的规则和步骤,变换结果为密文
密文:对明文进行变换的结果
解密算法:加密算法的逆变换,以密文为输入、**为参数,变换结果为明文
二、.对称密码常用的数学运算
对称密码当中有几种常用到的数学运算。这些运算的共同目的就是把被加密的明文数码尽可能深地打乱,从而加大破译的难度。
移位和循环移位
移位就是将一段数码按照规定的位数整体性地左移或右移。循环右移就是当右移时,把数码的最后的位移到数码的最前头,循环左移正相反。置换
就是将数码中的某一位的值根据置换表的规定,用另一位代替。通过置换将原文彻底打乱,加大解密难度。扩展
就是将一段数码扩展成比原来位数更长的数码。扩展方法有多种,例如,可以用置换的方法,以扩展置换表来规定扩展后的数码每一位的替代值。压缩
就是将一段数码压缩成比原来位数更短的数码。压缩方法有多种,例如,也可以用置换的方法,以表来规定压缩后的数码每一位的替代值。异或
参加异或的数如果相同为0,不同为1。
1⊕1 = 0
0⊕0 = 0
1⊕0 = 1
0⊕1 = 1迭代
迭代就是多次重复相同的运算,这在密码算法中经常使用,以使得形成的密文更加难以**。
三、DES算法简介
1. DES是一种将64比特的明文加密成64比特密文的对称密码算法,它的**长度是56位,尽管从本质上说它的**是64bit,但是由于每隔7位会设置一个用于错误检查的比特,奇偶校验位,因此实质上**长度是56比特。
2. DES以64比特明文为一个单位进行加密。
3. DES每次只能加密64比特的数据,如果待加密的数据比较长,就需要对DES加密进行迭代,迭代的具体方案称之为模式。如果数据长度不足64比特的倍数就需要进行填充。
四、DES算法的理论原理
DES算法的主要流程如下图所示
1. IP置换
IP置换目的是将输入的64位数据块按位重新组合,并把输出分为L0、R0两部分,每部分各长32位。
置换规则如下表所示:
表中的数字代表原数据中此位置的数据在新数据中的位置,即原数据块的第1位放到新数据的第58位,第2位放到第50位,……依此类推,第64位放到第7位。置换后的数据分为L0和R0两部分,L0为新数据的左32位,R0为新数据的右32位。
2. **置换
不考虑每个字节的第8位,DES的**由64位减至56位,每个字节的第8位作为奇偶校验位。产生的56位**由下表生成(注意表中没有8,16,24,32,40,48,56和64这8位):
在DES的每一轮中,从56位**产生出不同的48位子**,确定这些子**的方式如下:
(1).将56位的**分成两部分,每部分28位。
(2).根据轮数,这两部分分别循环左移1位或2位。每轮移动的位数如下表:
移动后,从56位中选出48位。这个过程中,既置换了每位的顺序,又选择了子**,因此称为压缩置换。压缩置换规则如下表(注意表中没有9,18,22,25,35,38,43和54这8位):
置换方法同上,此处省略。
3.扩展置换
扩展置置换目标是IP置换后获得的右半部分R0,将32位输入扩展为48位(分为4位×8组)输出。
扩展置换目的有两个:生成与**相同长度的数据以进行异或运算;提供更长的结果,在后续的替代运算中可以进行压缩。
扩展置换原理如下表:
表中的数字代表位,两列黄色数据是扩展的数据,可以看出,扩展的数据是从相邻两组分别取靠近的一位,4位变为6位。靠近32位的位为1,靠近1位的位为32。表中第二行的4取自上组中的末位,9取自下组中的首位。
4.S盒代替
压缩后的**与扩展分组异或以后得到48位的数据,将这个数据送人S盒,进行替代运算。替代由8个不同的S盒完成,每个S盒有6位输入4位输出。48位输入分为8个6位的分组,一个分组对应一个S盒,对应的S盒对各组进行代替操作。
5. P盒置换
S盒代替运算的32位输出按照P盒进行置换。该置换把输入的每位映射到输出位,任何一位不能被映射两次,也不能被略去,映射规则如下表:
表中的数字代表原数据中此位置的数据在新数据中的位置,即原数据块的第16位放到新数据的第1位,第7位放到第2位,……依此类推,第25位放到第32位。
最后,P盒置换的结果与最初的64位分组左半部分L0异或,然后左、右半部分交换,接着开始另一轮。
6.IP末置换
末置换是初始置换的逆过程,DES最后一轮后,左、右两半部分并未进行交换,而是两部分合并形成一个分组做为末置换的输入。末置换规则如下表:
五、Go语言使用DES算法实例
package main
import (
"crypto/des"
"bytes"
"crypto/cipher"
"fmt"
)
//为最后一组填充数据
func PaddingText(src []byte,blockSize int)[]byte{
length := len(src)%blockSize
//获取需要填充的字节数
padding := blockSize-length
//填充数据
paddText := bytes.Repeat([]byte{byte(padding)},padding)
//将填充数据追加到原始数据
newText := append(src,paddText...)
return newText
}
func UnPaddingText(src []byte) []byte{
length := len(src)
//取出原始数据最后一个字节
number := int(src[length-1])
//去除填充数据
newText := src[:length-number]
return newText
}
//使用DES算法对文件进行加密
//src:需要被加密的明文
//key:秘钥
func EncryptDES(src,key []byte)([]byte,error){
//生成加密用的block
block,err :=des.NewCipher(key)
if err!=nil{
return []byte(""),err
}
length := block.BlockSize()
//拼接数据
src = PaddingText(src,length)
//NewCBCEncrypter第二个参数是初始化向量,长度要求和块大小一样,内容随意(需要和解密初始化向量相同)
//根据块和向量创建CBC加密模式
blockMode := cipher.NewCBCEncrypter(block,key[:block.BlockSize()])
//创建切片,用于存储加密之后的密文
dest := make([]byte,len(src))
//加密
blockMode.CryptBlocks(dest,src)
return dest,nil
}
//使用DES算法解密
//src:需要被加密的密文
//key:秘钥,需要和加密时使用的秘钥相同
func DecryptDES(src,key []byte)([]byte,error){
block,err :=des.NewCipher(key)
if err != nil{
return []byte(""),err
}
//准备初始化向量
//创建解密模式
blockMode := cipher.NewCBCDecrypter(block,key[:block.BlockSize()])
//创建切片,用于存储解密之后的明文
dest := make([]byte,len(src))
//解密
blockMode.CryptBlocks(dest,src)
NewText := UnPaddingText(dest)
return NewText,nil
}
func main(){
src := []byte("单枪匹马你别怕,一腔孤勇又如何!")
key := []byte("00001111")
ciphertext,err := EncryptDES(src,key)
if err != nil{
fmt.Println("Encrypt err:",err)
return
}
fmt.Println(ciphertext)
plaintext,err := DecryptDES(ciphertext,key)
if err != nil{
fmt.Println("Decrypt err:",err)
return
}
fmt.Println(string(plaintext))
}