加密算法簡(jiǎn)介
加密算法就是加密的方法敬尺,在密碼學(xué)中肢执,加密是將明文信息隱藏起來(lái)练慕,使之缺少特殊信息時(shí)不可讀惰匙。加密算法可以分為兩類:對(duì)稱加密和非對(duì)稱加密。
1. 對(duì)稱加密
將信息使用一個(gè)密鑰進(jìn)行加密铃将,解密時(shí)使用同樣的密鑰项鬼,同樣的算法進(jìn)行解密。
2. 非對(duì)稱加密
非對(duì)稱加密又稱公開(kāi)密鑰加密劲阎,密鑰分為私密密鑰和公開(kāi)密鑰绘盟,通過(guò)公鑰加密,私鑰解密的過(guò)程悯仙,并且加密和解密算法不同龄毡。
關(guān)于對(duì)稱加密
對(duì)稱加密是加密和解密雙方持有相同的私鑰,即加密方通過(guò)密鑰執(zhí)行加密過(guò)程锡垄,解密方通過(guò)相同的密鑰執(zhí)行解密過(guò)程沦零,因?yàn)殡p方持有相同的密鑰,所以叫做對(duì)稱加密货岭。同時(shí)路操,因?yàn)槊荑€理論上只有加解密雙方持有,所以也叫做私鑰加密千贯。常見(jiàn)的對(duì)稱加密算法有:DES屯仗,3DES,AES以及RC4等丈牢。
對(duì)稱加密分為序列密碼和分組密碼兩類祭钉,如下圖:
1. 序列密碼
序列密碼單獨(dú)加密每個(gè)位,它是通過(guò)將密鑰序列中的每個(gè)位 與每個(gè)明文位相加實(shí)現(xiàn)的己沛。同步序列密碼的密碼序列僅僅取決于密鑰慌核,而異步序列密碼序列則取決于密鑰和密文,如RC4申尼。
2. 分組密碼
分組密碼每次使用相同的密鑰加密整個(gè)明文位分組垮卓。這意味著對(duì)給定分組內(nèi)任何明文位的加密都依賴于與它同在一個(gè)分組內(nèi)的其他所有明文位。絕大多數(shù)分組密碼的分組長(zhǎng)度要么是128位(16字節(jié))师幕,比如AES粟按,要么是64位(8字節(jié))诬滩,比如DES和3DES。
對(duì)稱加密特點(diǎn)
- 算法可逆灭将,即加密后可以通過(guò)解密還原數(shù)據(jù)疼鸟。
- 加密效率高,加密速度快
- 安全性沒(méi)有非對(duì)稱加密高庙曙,因?yàn)槊荑€分發(fā)時(shí)存在安全隱患
對(duì)稱加密算法
在寫對(duì)稱加密算法之前空镜,有必要先提一下分組加密的操作模式有哪些,因?yàn)榉纸M加密是對(duì)稱加密中應(yīng)用最多的加密方式捌朴,并且可以有不同的操作模式吴攒。
分組加密模式
1. 電子密碼本模式(ECB)
ECB模式要求明文長(zhǎng)度必須是所使用密碼的分組大小的整數(shù)倍,比如在AES(后面會(huì)提到)中砂蔽,明文長(zhǎng)度應(yīng)該是16字節(jié)的整數(shù)倍洼怔,如果不滿足此長(zhǎng)度要求,則必須對(duì)其進(jìn)行填充左驾,填充的方式有很多種镣隶,比如:在明文后附加單個(gè)"1",然后再根據(jù)需要附加足夠多的"0"位什荣,直到明文的長(zhǎng)度達(dá)到分組長(zhǎng)度的整數(shù)倍矾缓,如果明文的長(zhǎng)度剛好是分組長(zhǎng)度的整數(shù)倍,則填充的所有位剛好形成了一個(gè)單獨(dú)的額外分組稻爬。ECB加密解密如下圖:
其中表示明文分組嗜闻,e表示加密方法,k為密鑰桅锄,
表示密文分組琉雳,
表示解密方法。假設(shè)分組密碼加密(解密)的分組大小為b位友瘤,長(zhǎng)度超過(guò)b位的消息將被分割為大小為b位的分組翠肘,如果消息長(zhǎng)度不是b位的整數(shù)倍,則在加密前必須將其填充位b位的整數(shù)倍辫秧。ECB模式中的每個(gè)分組都是單獨(dú)加密的束倍,
ECB優(yōu)缺點(diǎn):
- 加密和解密之間的分組同步不是必須的,即如果數(shù)據(jù)丟失盟戏,接收方還是可能解密已收到的分組绪妹。
- 加密高度確定,即只要密鑰不變柿究,相同的明文分組總是產(chǎn)生相同的密文分組邮旷。
- 明文分組的加密是完全獨(dú)立的,與前面的分組沒(méi)有任何關(guān)系蝇摸。如果攻擊者將密文分組重新排序婶肩,有可能會(huì)得到有效的明文办陷。
- 密碼分組鏈接模式(CBC)
2. 密碼分組鏈接模式(CBC)
CBC模式主要基于兩種思想。第一律歼,所有分組的加密都鏈接在一起民镜,是得密文不僅依賴
,而且還依賴前面所有的明文分組苗膝。第二殃恒,加密過(guò)程使用的初始向量(IV)進(jìn)行了隨機(jī)化。
密文是明文
加密后的結(jié)果辱揭,它將反饋為密碼輸入,并與后續(xù)明文分組
進(jìn)行異或操作病附,然后將得到的異或和進(jìn)行加密问窃,得到下一個(gè)密文
,而這個(gè)密文將被用來(lái)加密
完沪,以此類推域庇。整個(gè)過(guò)程如下圖所示。
由于第一個(gè)明文分組沒(méi)有前向密文覆积,所以將IV與第一個(gè)明文相加會(huì)使每輪的CBC加密變得不確定听皿。
注意:第一個(gè)密文取決于明文
(和IV);第二個(gè)密文
則取決于IV宽档、
和
尉姨;第三個(gè)明文取決于IV、
吗冤、
和
又厉,以此類推。最后一個(gè)密文則是所有明文分組和IV的函數(shù)椎瘟。
3. 輸出反饋模式(OFB)
OFB模式使用分組密碼來(lái)構(gòu)建一個(gè)序列密鑰加密方案覆致。注意,在OFB模式中肺蔚,密鑰序列不是按位產(chǎn)生煌妈,而是以分組方式產(chǎn)生。密碼的輸出是b個(gè)密鑰序列位宣羊,其中b為所使用的分組密碼的寬度璧诵;將b為的明文與該b位的密鑰序列進(jìn)行異或操作即可實(shí)現(xiàn)對(duì)明文的加密。如下圖:
OFB模式首先使用分組密碼加密IV段只,得到的密鑰輸出為b位密鑰序列的第一個(gè)集合腮猖;將前一個(gè)密鑰輸出反饋給分組密碼進(jìn)行加密,即可計(jì)算出密鑰序列位的下一個(gè)分組赞枕;不斷重復(fù)此過(guò)程澈缺。
因?yàn)槭褂玫氖峭叫蛄忻艽a坪创,所以加密與解密操作完全相同,且加密解密位異或操作姐赡。OFB的一個(gè)優(yōu)點(diǎn)就是分組密碼的計(jì)算與明文無(wú)關(guān)莱预。因此,可以預(yù)計(jì)算密鑰序列材料的一個(gè)或多個(gè)分組项滑。
4. 密碼反饋模式(CFB)
CFB模式也使用分組密碼作為構(gòu)建序列密碼的基本元件依沮,與OFB模式相同的是,CFB也使用了反饋枪狂;而不同的是危喉,OFB反饋的是分組密碼的輸出,而CFB反饋的是密文州疾。OFB的基本思想是:要生成第一個(gè)密鑰序列分組辜限,必須先加密IV;而所有后續(xù)密鑰序列分組
严蓖,
薄嫡,...都是通過(guò)加密前一個(gè)密文得到的。如下圖所示:
根據(jù)序列密碼加密颗胡,CFB加密解密操作也完全相同毫深,但CFB模式是一個(gè)異步序列密鑰加密
5. 計(jì)數(shù)器模式(CTR)
與OFB和CFB模式一樣,密鑰序列也是以分組方式計(jì)算的毒姨。分組密碼的輸入為一個(gè)計(jì)數(shù)器哑蔫,每當(dāng)分組密碼計(jì)算一個(gè)新密鑰序列分組時(shí),該計(jì)數(shù)器都會(huì)產(chǎn)生一個(gè)不同的值手素,如下圖所示:
初始化分組密碼的輸入時(shí)必須避免兩次使用相同過(guò)的輸入值鸳址,如果攻擊者知道了使用相同輸入加密的明文中的任何一個(gè),就可以計(jì)算出密鑰序列分組泉懦,從而可以解密其他明文稿黍。計(jì)數(shù)器模式最大的特點(diǎn)就是并行化,因?yàn)橛?jì)數(shù)器模式不需要任何反饋崩哩。加入有兩個(gè)分組加密引擎巡球,即可以讓兩個(gè)引擎同時(shí)使用第一個(gè)分組密碼加密計(jì)數(shù)器值和
,這兩個(gè)分組密碼引擎完成后邓嘹,一個(gè)繼續(xù)加密
酣栈,而另一個(gè)則加密
。
6. 伽羅瓦計(jì)數(shù)器模式(GCM)
GCM是一種計(jì)算消息驗(yàn)證碼的加密模式汹押。MAC(消息驗(yàn)證碼)由發(fā)送者計(jì)算密碼校驗(yàn)和矿筝,并附加在消息后面,接收方也會(huì)計(jì)算此消息的密碼校驗(yàn)和棚贾,并校驗(yàn)與發(fā)送者發(fā)送過(guò)來(lái)的是否相同窖维,這樣便可以確認(rèn)消失是否是發(fā)送者發(fā)送過(guò)來(lái)的榆综,且密文是否有被修改過(guò)。
主流對(duì)稱加密算法實(shí)現(xiàn)(Go語(yǔ)言)
下面將逐一介紹上面提到的對(duì)稱加密的算法實(shí)現(xiàn)铸史。
1. RC4
RC4為流加密算法鼻疮,即前面提到的序列加密,由偽隨機(jī)數(shù)生成器和異或運(yùn)算組成琳轿,密鑰長(zhǎng)度可變判沟,范圍在[1,255]。RC4一個(gè)字節(jié)一個(gè)字節(jié)地加解密崭篡,由于采用的是異或運(yùn)算挪哄,使用的是同一套算法。
func Encrypt(bytes []byte, key []byte) ([]byte, error) {
c, err := rc4.NewCipher(key)
if err != nil {
return nil, err
}
var dst = make([]byte, len(bytes))
c.XORKeyStream(dst, bytes)
return dst, nil
}
//RC4為序列密碼加密琉闪,采用異或運(yùn)算中燥,所以此處直接調(diào)用解密算法
func Decrypt(encryptData, key []byte) ([]byte, error) {
return Encrypt(encryptData, key)
}
2. DES(3DES)
DES是一種使用56位(7字節(jié))(注:其實(shí)DES的輸入密鑰是64位(8字節(jié)),但是每個(gè)字節(jié)的第8位都作為前面7位的一個(gè)奇校驗(yàn)位塘偎,所以實(shí)際密鑰有效位為56位。)密鑰對(duì)64位(8字節(jié))長(zhǎng)分組進(jìn)行加密的算法拿霉,加吟秩、解密過(guò)程使用相同對(duì)密鑰。
DES算法機(jī)制為迭代绽淘,一共16輪涵防,每輪操作完全相同,但使用不同的子密鑰沪铭,子密鑰都是由主密鑰推導(dǎo)而來(lái)的壮池,都是從輸入密鑰中選擇48個(gè)置換位。DES加密流程如下:
3DES即為三重DES加密杀怠,3DES加密密鑰長(zhǎng)度為192位(24字節(jié))椰憋。
解密過(guò)程主要為密鑰編排逆轉(zhuǎn),即解密的第一輪需要子密鑰16赔退;第二輪需要子密鑰15橙依;以此類推。
func Encrypt(plainText []byte, key []byte) ([]byte, error) {
//block, err := des.NewTripleDESCipher(key)為三重DES加密
block, err := des.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize() //分組大小
plainText = paddingWithPKCS5(plainText, blockSize) //填充
var cipherText = make([]byte, len(plainText))
//ECB每個(gè)分組單獨(dú)加密
var temp = cipherText
for len(plainText) > 0 {
block.Encrypt(temp, plainText[:blockSize])
plainText = plainText[blockSize:]
temp = temp[blockSize:]
}
return cipherText, nil
}
func Decrypt(cipherText []byte, key []byte) ([]byte, error) {
//block, err := des.NewTripleDESCipher(key)為三重DES加密
block, err := des.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize() //分組大小
var plainText = make([]byte, len(cipherText))
//ECB每個(gè)分組單獨(dú)加密
var temp = plainText
for len(cipherText) > 0 {
block.Decrypt(temp, cipherText[:blockSize])
cipherText = cipherText[blockSize:]
temp = temp[blockSize:]
}
plainText = unPaddingWithPKCS5(plainText)
return plainText, nil
}
func paddingWithPKCS5(data []byte, blockSize int) []byte {
//需要填充的值以及數(shù)量
padding := blockSize - len(data)%blockSize
//組裝填充值([]byte)
var paddingData = []byte{byte(padding)}
paddingData = bytes.Repeat(paddingData, padding)
//append填充
data = append(data, paddingData...)
return data
}
func unPaddingWithPKCS5(data []byte) []byte {
padding := int(data[len(data)-1])
return data[:len(data)-padding]
}
3. AES
AES擁有三種不同的密鑰長(zhǎng)度抵抗蠻力攻擊硕旗,分別為128位窗骑,192位和256位,分組大小為128位漆枚。
func Encrypt(plainText []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize() //分組大小
plainText = paddingWithPKCS5(plainText, blockSize) //填充
var cipherText = make([]byte, len(plainText))
//CBC模式
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
blockMode.CryptBlocks(cipherText,plainText)
return cipherText, nil
}
func Decrypt(cipherText []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize() //分組大小
var plainText = make([]byte, len(cipherText))
//CBC模式
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
blockMode.CryptBlocks(plainText, cipherText)
plainText = unPaddingWithPKCS5(plainText)
return plainText, nil
}
引用資料
《維基百科》
《深入淺出密碼學(xué)——常用加密技術(shù)原理與應(yīng)用》
最后
原文鏈接
如有錯(cuò)誤创译,請(qǐng)不吝賜教!
Thanks!
附上代碼鏈接[github.com/pyihe/secret]