1. 什么是DES
DES(Data Encryption Standard)是1977年美國聯(lián)邦信息處理標準(FIPS)中所采用的一種對稱密碼 (FIPS46.3)做鹰。DES一直以來被美國以及其他國家的政府和銀行等廣泛使用俏站。然而慢味,隨著計算機的進步亲桦,現(xiàn)在 DES已經(jīng)能夠被暴力破解,強度大不如前了蜀备。
RSA公司舉辦過破澤DES密鑰的比賽(DESChallenge)蚁孔,我們可以看一看RSA公司官方公布的比賽結(jié)果:
- 1997年的DES Challenge1中用了96天破譯密鑰
- 1998年的DES ChallengeIl-I中用了41天破譯密鑰
- 1998年的DES ChallengeII-2中用了56小時破譯密鑰
- 1999年的DES ChallengeIll中只用了22小時15分鐘破譯密鑰
由于DES的密文可以在短時間內(nèi)被破譯,因此除了用它來解密以前的密文以外豪筝,現(xiàn)在我們不應(yīng)該再使用DES了痰滋。
2. DES加密和解密
DES是一種將64比特的明文加密成64比特的密文的對稱密碼算法摘能, 它的密鑰長度是56比特 。盡管從規(guī)格上來說即寡,DES的密鑰長度是64比特徊哑,但由于每隔7比特會設(shè)置一個用于錯誤檢查的比特,因此實質(zhì)上其密鑰長度是56 比特聪富。
DES是以64比特的明文(比特序列)為一個單位來進行加密的莺丑, 這個64比特的單位稱為分組。一般來說墩蔓,以分 組為單位進行處理的密碼算法稱為分組密碼(blockcipher)梢莽,DES就是分組密碼的一種。
3. Go語言中對DES的操作
3.1. 加解密實現(xiàn)思路
3.1.1. 加密 - CBC分組模式
- 創(chuàng)建并返回一個使用DES算法的cipher.Block接口
1.1 秘鑰長度為64bit, 即 64/8 = 8字節(jié)(byte)
- 創(chuàng)建并返回一個使用DES算法的cipher.Block接口
- 對最后一個明文分組進行數(shù)據(jù)填充
2.1 DES是以64比特的明文(比特序列)為一個單位來進行加密的
2.2 最后一組不夠64bit, 則需要進行數(shù)據(jù)填充( 參考第三章)
- 對最后一個明文分組進行數(shù)據(jù)填充
- 創(chuàng)建一個密碼分組為鏈接模式的, 底層使用DES加密的BlockMode接口
- 加密連續(xù)的數(shù)據(jù)塊
3.1.2. 解密
- 創(chuàng)建并返回一個使用DES算法的cipher.Block接口
- 創(chuàng)建一個密碼分組為鏈接模式的, 底層使用DES解密的BlockMode接口
- 數(shù)據(jù)塊解密
- 去掉最后一組的填充數(shù)據(jù)
3.2. 加解密的代碼實現(xiàn)
分組添加填充數(shù)據(jù)和移除添加數(shù)據(jù)代碼:
/*
* 使用PKCS#7的方式填充
*/
func PKCS7Padding(cipherText []byte, blockSize int) []byte {
// 計算最后一個分組缺多少個字節(jié)
padding := blockSize - (len(cipherText) % blockSize)
// 創(chuàng)建一個大小為padding的切片, 每個字節(jié)的值為padding
padText := bytes.Repeat([]byte{byte(padding)}, padding)
// 將padText添加到原始數(shù)據(jù)的后邊, 將最后一個分組缺少的字節(jié)數(shù)補齊
newText := append(cipherText, padText...)
return newText
}
/*
* 使用PKCS#7的方式移除
*/
func PKCS7UnPadding(origData []byte) []byte{
// 計算數(shù)據(jù)的總長度
length := len(origData)
// 根據(jù)填充的字節(jié)值得到填充的次數(shù)
number := int(origData[length-1])
// 將尾部填充的number個字節(jié)去掉
return origData[:(length-number)]
}
DES加密代碼:
/*
* DES加密奸披,CBC分組模式
*
* scr:要加密的明文
* key:秘鑰昏名,大小為8byte
* vi:初始向量,大小為8byte
*/
func DesCBCEncrypt(src, key, vi []byte) []byte {
// 創(chuàng)建并返回一個使用DES算法的cipher.Block接口
block, err := des.NewCipher(key)
// 判斷是否創(chuàng)建成功
if err != nil {
panic(err)
}
// 對明文進行數(shù)據(jù)填充(PKCS#7模式)
src = tools.PKCS7Padding(src, block.BlockSize())
// 創(chuàng)建一個密碼分組阵面,鏈接模式轻局, 底層使用DES加密的BlockMode接口
blockMode := cipher.NewCBCEncrypter(block, vi)
// 加密連續(xù)的數(shù)據(jù)塊
dst := src
blockMode.CryptBlocks(dst, src)
return dst
}
DES解密代碼:
/*
* DES解密,CBC分組模式
*
* scr:要解密的密文
* key:秘鑰样刷,大小為8byte
* vi:初始向量仑扑,大小為8byte
*/
func DesCBCDecrypt(src, key, vi []byte) []byte {
// 創(chuàng)建并返回一個使用DES算法的cipher.Block接口
block, err := des.NewCipher(key)
// 判斷是否創(chuàng)建成功
if err != nil {
panic(err)
}
// 創(chuàng)建一個密碼分組為鏈接模式的, 底層使用DES解密的BlockMode接口
blockMode := cipher.NewCBCDecrypter(block, vi)
// 解密數(shù)據(jù)
dst := src
blockMode.CryptBlocks(src, dst)
// 去掉最后一組填充的數(shù)據(jù)
dst = tools.PKCS7UnPadding(dst)
return dst
}
測試函數(shù):
func testDES() {
key := []byte("erlengzi")
result := des.DesCBCEncrypt([]byte("床前明月光, 疑是地上霜. 舉頭望明月, 低頭思故鄉(xiāng)."),key, key)
fmt.Println(string(result))
result = des.DesCBCDecrypt(result, key, key)
fmt.Println(string(result))
}
4. 三重DES
現(xiàn)在DES已經(jīng)可以在現(xiàn)實的時間內(nèi)被暴力破解,因此我們需要一種用來替代DES的分組密碼置鼻,三重DES就是出于 這個目的被開發(fā)出來的镇饮。
三重DES(triple-DES)是為了增加DES的強度, 將DES重復(fù)3次所得到的一種密碼算法 箕母,通炒⒚辏縮寫為3DES。
4.1. 三重DES的加解密
三重DES的加解密機制如圖所示:
明文經(jīng)過三次DES處理才能變成最后的密文嘶是,由于 DES密鑰的長度實質(zhì)上是56比特 钙勃,因此三重DES的密鑰長度就 是56×3=168比特, 加上用于錯誤檢測的標志位8x3, 共192bit。
從上圖我們可以發(fā)現(xiàn)聂喇,三重DES并不是進行三次DES加密(加密-->加密-->加密)辖源,而是 加密-->解密-->加密 的過 程。在加密算法中加人解密操作讓人感覺很不可思議授帕,實際上這個方法是IBM公司設(shè)計出來的同木,目的是為了讓三 重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枉证。
盡管三重DES目前還被銀行等機構(gòu)使用矮男,但其處理速度不高,而且在安全性方面也逐漸顯現(xiàn)出了一些問題室谚。
4.2. Go中對3DES的操作
4.2.1. 加解密實現(xiàn)思路
加密 - CBC分組模式
- 創(chuàng)建并返回一個使用3DES算法的cipher.Block接口
1.1 秘鑰長度為64bit*3=192bit, 即 192/8 = 24字節(jié)(byte)
- 創(chuàng)建并返回一個使用3DES算法的cipher.Block接口
- 對最后一個明文分組進行數(shù)據(jù)填充
2.1 3DES是以64比特的明文(比特序列)為一個單位來進行加密的
2.2 最后一組不夠64bit, 則需要進行數(shù)據(jù)填充( 參考第三章)
- 對最后一個明文分組進行數(shù)據(jù)填充
- 創(chuàng)建一個密碼分組為鏈接模式的, 底層使用3DES加密的BlockMode接口
- 加密連續(xù)的數(shù)據(jù)塊
解密
- 創(chuàng)建并返回一個使用3DES算法的cipher.Block接口
- 創(chuàng)建一個密碼分組為鏈接模式的, 底層使用3DES解密的BlockMode接口
- 數(shù)據(jù)塊解密
- 去掉最后一組的填充數(shù)據(jù)
4.2.2. 加解密的代碼實現(xiàn)
3DES加密代碼:
/*
* 3DES加密毡鉴,CBC分組模式
*
* scr:要加密的明文
* key:秘鑰,大小為24byte
* vi:初始向量秒赤,大小為8byte
*/
func TripleDesCBCEncrypt(src, key, vi []byte) []byte {
// 創(chuàng)建并返回一個使用3DES算法的cipher.Block接口
block, err := des.NewTripleDESCipher(key)
if err != nil {
panic(err)
}
// 對最后一組明文進行填充
src = tools.PKCS7Padding(src, block.BlockSize())
// 創(chuàng)建一個密碼分組為鏈接模式, 底層使用3DES加密的BlockMode模型
blockMode := cipher.NewCBCEncrypter(block, vi)
// 加密數(shù)據(jù)
dst := src
blockMode.CryptBlocks(dst, src)
return dst
}
DES解密代碼:
/*
* 3DES解密猪瞬,CBC分組模式
*
* scr:要解密的密文
* key:秘鑰,大小為24byte
* vi:初始向量倒脓,大小為8byte
*/
func TripleDesCBCDecrypt(src, key, vi []byte) []byte {
// 創(chuàng)建3DES算法的Block接口對象
block, err := des.NewTripleDESCipher(key)
if err != nil{
panic(err)
}
// 創(chuàng)建密碼分組為鏈接模式, 底層使用3DES解密的BlockMode模型
blockMode := cipher.NewCBCDecrypter(block, vi)
// 解密
dst := src
blockMode.CryptBlocks(dst, src)
// 去掉尾部填充的數(shù)據(jù)
dst = tools.PKCS7UnPadding(dst)
return dst
}
測試函數(shù):
func test3DES() {
key := []byte("erlengzi1234567887654321")
result := des.TripleDesCBCEncrypt([]byte("床前明月光, 疑是地上霜. 舉頭望明月, 低頭思故鄉(xiāng)."),key, key[:8])
fmt.Println(string(result))
result = des.TripleDesCBCDecrypt(result, key, key[:8])
fmt.Println(string(result))
}