一、对称加密算法
目前加解密算法分为两类,对称加密和非对称加密,对称加密使用同一个密钥对信息进行加密和解密,代表的算法主要有:3DES、AES 等。非对称加密的密钥分为公钥和私钥两个,加密使用公钥,解密使用私钥,反之亦可,代表算法有:RSA、椭圆曲线加密等
对称加密的加密密钥能够从解密密钥中推算出来,同时解密密钥也可以从加密密钥中推算出来。而在大多数的对称算法中,加密密钥和解密密钥是相同的,所以也称这种加密算法为秘密密钥算法或单密钥算法。它要求发送方和接收方在安全通信之前,商定一个密钥。对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人都可以对他们发送或接收的消息解密,所以密钥的保密性对通信的安全性至关重要。
对称算法又可分为两类。一次只对明文中的单个位(有时对字节)运算的算法称为序列算法或序列密码。另一类算法是对明文的一组位进行运算,这些位组称为分组,相应的算法称为分组算法或分组密码。现代计算机密码算法的典型分组长度为64位――这个长度既考虑到分析破译密码的难度,又考虑到使用的方便性。后来,随着破译能力的发展,分组长度又提高到128位或更长。
在对称加密算法中,加密算法一般如下所示:
明文:待需要加密的原始文件
密钥:加密所需要的key值
加密算法:以密钥为参数,对明文进行多种置换和转换的规则和步骤,变换结果为密文
密文:对明文进行变换的结果
解密算法:加密算法的逆变换,以密文为输入、密钥为参数,变换结果为明文
二、对称加密算法优缺点
-
优点:
计算量小
加密速度快
加密效率高 -
缺点:
双方都使用同样密钥,安全性得不到保证
密钥管理困难,使用成本较高
三、.对称密码常用的数学运算
对称密码当中有几种常用到的数学运算。这些运算的共同目的就是把被加密的明文数码尽可能深地打乱,从而加大破译的难度。
-
移位和循环移位
移位就是将一段数码按照规定的位数整体性地左移或右移。循环右移就是当右移时,把数码的最后的位移到数码的最前头,循环左移正相反。 -
置换
就是将数码中的某一位的值根据置换表的规定,用另一位代替。通过置换将原文彻底打乱,加大解密难度。 -
扩展
就是将一段数码扩展成比原来位数更长的数码。扩展方法有多种,例如,可以用置换的方法,以扩展置换表来规定扩展后的数码每一位的替代值。 -
压缩
就是将一段数码压缩成比原来位数更短的数码。压缩方法有多种,例如,也可以用置换的方法,以表来规定压缩后的数码每一位的替代值。 -
异或
参加异或的数如果相同为0,不同为1。
1⊕1 = 0
0⊕0 = 0
1⊕0 = 1
0⊕1 = 1 -
迭代
迭代就是多次重复相同的运算,这在密码算法中经常使用,以使得形成的密文更加难以破解。
五、分组加密和流加密介绍
- 分组加密又称块加密,把明文按照块的大小分为数个块,并对每个块进行独立加密。
- 流加密是采用算法和密钥生成一个随机码流,再与明文进行异或操作。
六、DES算法简介
1. DES 是一个分组加密算法,以 64 位为分组对数据加密,加解密用的是同一个算法。将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最后一轮后,左、右两半部分并未进行交换,而是两部分合并形成一个分组做为末置换的输入。末置换规则如下表:
八、DES 解密
在了解了加密过程中所有的置换、异或和循环移位之后,大家也许会认为,解密算法应该是加密的逆运算,与加密算法完全不同。神奇的是,DES 获的加密和解密使用的是相同的算法!只有密钥顺序不同,是相反的。如果各轮加密密钥分别是 K1、K2、K3…K16,那么解密密钥就是 K16、K15、K14…K1。
九、DES 安全性
DES 的安全性首先取决于密钥的长度。密钥越长,破译者利用穷举法搜索密钥的难度就越大。目前计算机的处理速度和能力,56 位长度的密钥已经能够被破解,称不上安全了,所以出现了 3DES,安全性大大提高。
十、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()
//拼接数据,即,DES加密的明文长度为64位
// 少于64位可以填充,多余64位可以根据64位一块,形成多个块,不够的填充。
//block.BlockSize()就是加密的块长度,fill函数会将明文按照块长度进行分组。
//这样就形成了多个明文分组。以便于进行DES加密
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))
}