對稱加密之DES

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就是分組密碼的一種。

DES的加密與解密 - 圖例.png

3. Go語言中對DES的操作

3.1. 加解密實現(xiàn)思路

3.1.1. 加密 - CBC分組模式
    1. 創(chuàng)建并返回一個使用DES算法的cipher.Block接口
      1.1 秘鑰長度為64bit, 即 64/8 = 8字節(jié)(byte)
    1. 對最后一個明文分組進行數(shù)據(jù)填充
      2.1 DES是以64比特的明文(比特序列)為一個單位來進行加密的
      2.2 最后一組不夠64bit, 則需要進行數(shù)據(jù)填充( 參考第三章)
    1. 創(chuàng)建一個密碼分組為鏈接模式的, 底層使用DES加密的BlockMode接口
    1. 加密連續(xù)的數(shù)據(jù)塊
3.1.2. 解密
    1. 創(chuàng)建并返回一個使用DES算法的cipher.Block接口
    1. 創(chuàng)建一個密碼分組為鏈接模式的, 底層使用DES解密的BlockMode接口
    1. 數(shù)據(jù)塊解密
    1. 去掉最后一組的填充數(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的加解密機制如圖所示:


三重DES加密.png
三重DES解密.png

明文經(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分組模式

    1. 創(chuàng)建并返回一個使用3DES算法的cipher.Block接口
      1.1 秘鑰長度為64bit*3=192bit, 即 192/8 = 24字節(jié)(byte)
    1. 對最后一個明文分組進行數(shù)據(jù)填充
      2.1 3DES是以64比特的明文(比特序列)為一個單位來進行加密的
      2.2 最后一組不夠64bit, 則需要進行數(shù)據(jù)填充( 參考第三章)
    1. 創(chuàng)建一個密碼分組為鏈接模式的, 底層使用3DES加密的BlockMode接口
    1. 加密連續(xù)的數(shù)據(jù)塊

解密

    1. 創(chuàng)建并返回一個使用3DES算法的cipher.Block接口
    1. 創(chuàng)建一個密碼分組為鏈接模式的, 底層使用3DES解密的BlockMode接口
    1. 數(shù)據(jù)塊解密
    1. 去掉最后一組的填充數(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))
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末撑螺,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子崎弃,更是在濱河造成了極大的恐慌甘晤,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饲做,死亡現(xiàn)場離奇詭異线婚,居然都是意外死亡,警方通過查閱死者的電腦和手機盆均,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門塞弊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人泪姨,你說我怎么就攤上這事游沿。” “怎么了肮砾?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵诀黍,是天一觀的道長。 經(jīng)常有香客問我仗处,道長眯勾,這世上最難降的妖魔是什么枣宫? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮吃环,結(jié)果婚禮上也颤,老公的妹妹穿的比我還像新娘。我一直安慰自己郁轻,他們只是感情好翅娶,可當我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著好唯,像睡著了一般故觅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上渠啊,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天输吏,我揣著相機與錄音,去河邊找鬼替蛉。 笑死贯溅,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的躲查。 我是一名探鬼主播它浅,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼镣煮!你這毒婦竟也來了姐霍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤典唇,失蹤者是張志新(化名)和其女友劉穎镊折,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體介衔,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡恨胚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了炎咖。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赃泡。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖乘盼,靈堂內(nèi)的尸體忽然破棺而出升熊,到底是詐尸還是另有隱情,我是刑警寧澤绸栅,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布级野,位于F島的核電站,受9級特大地震影響阴幌,放射性物質(zhì)發(fā)生泄漏勺阐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一矛双、第九天 我趴在偏房一處隱蔽的房頂上張望渊抽。 院中可真熱鬧,春花似錦议忽、人聲如沸懒闷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽愤估。三九已至,卻和暖如春速址,著一層夾襖步出監(jiān)牢的瞬間玩焰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工芍锚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留昔园,地道東北人。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓并炮,卻偏偏與公主長得像默刚,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子逃魄,可洞房花燭夜當晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容