人才 對稱加密 異或運算 加密和解密 enc aes 其中 binary 錯誤

區塊鏈教程區塊鏈背後的信息安全2DES、3DES加密算法原理一,2018年下半年,區塊鏈行業正逐漸褪去發展之初的浮躁、回歸理性,表面上看相關人才需求與身價似乎正在回落。但事實上,正是初期泡沫的漸退,讓人們更多的關註點放在了區塊鏈真正的技術之上。

DES、3DES加密算法原理及其GO語言實現

DES加密算法,為對稱加密算法中的一種。70年代初由IBM研發,後1977年被美國國家標準局采納為數據加密標準,即DES全稱的由來:Data Encryption Standard。
對稱加密算法,是相對於非對稱加密算法而言的。兩者區別在於,對稱加密在加密和解密時使用同一密鑰,而非對稱加密在加密和解密時使用不同的密鑰,即公鑰和私鑰。
常見的DES、3DES、AES均為對稱加密算法,而RSA、橢圓曲線加密算法,均為非對稱加密算法。

DES是以64比特的明文為一個單位來進行加密的,超過64比特的數據,要求按固定的64比特的大小分組,分組有很多模式,後續單獨總結,暫時先介紹DES加密算法。
DES使用的密鑰長度為64比特,但由於每隔7個比特設置一個奇偶校驗位,因此其密鑰長度實際為56比特。奇偶校驗為最簡單的錯誤檢測碼,即根據一組二進制代碼中1的個數是奇數或偶數來檢測錯誤。

Feistel網絡

DES的基本結構,由IBM公司的Horst Feistel設計,因此稱Feistel網絡。
在Feistel網絡中,加密的每個步驟稱為輪,經過初始置換後的64位明文,進行了16輪Feistel輪的加密過程,最後經過終結置換後形成最終的64位密文。

64比特明文被分為左、右兩部分處理,右側數據和子密鑰經過輪函數f生成用於加密左側數據的比特序列,與左側數據異或運算,運算結果輸出為加密後的左側,右側數據則直接輸出為右側。
其中子密鑰為本輪加密使用的密鑰,每次Feistel均使用不同的子密鑰。子密鑰的計算,以及輪函數的細節,稍後下文介紹。
由於一次Feistel輪並不會加密右側,因此需要將上一輪輸出後的左右兩側對調後,重復Feistel輪的過程,DES算法共計進行16次Feistel輪,最後一輪輸出後左右兩側無需對調。

DES加密和解密的過程一致,均使用Feistel網絡實現,區別僅在於解密時,密文作為輸入,並逆序使用子密鑰。

go標準庫中DES算法實現如下:

func cryptBlock(subkeys []uint64, dst, src []byte, decrypt bool) {
????b := binary.BigEndian.Uint64(src)
????//初始置換
????b = permuteInitialBlock(b)
????left, right := uint32(b>>32), uint32(b)

????var subkey uint64
????//共計16次feistel輪
????for i := 0; i < 16; i++ {
????????//加密和解密使用子密鑰順序相反
????????if decrypt {
????????????subkey = subkeys[15-i]
????????} else {
????????????subkey = subkeys[i]
????????}
????????//feistel輪函數
????????left, right = right, left^feistel(right, subkey)
????}
????//最後一輪無需對調
????preOutput := (uint64(right) << 32) | uint64(left)
????//終結置換
????binary.BigEndian.PutUint64(dst, permuteFinalBlock(preOutput))
}
//代碼位置src/crypto/des/block.go

初始置換和終結置換

進入Feistel輪之前,64位明文需做一次初始置換。Feistel輪結束後,需做一次反向操作,即終結置換。
初始置換和終結置換目的是為加強硬件的破解難度而加的。

附go標準庫中使用的初始置換表和終結置換表如下:

//初始置換表
var initialPermutation = [64]byte{
????6, 14, 22, 30, 38, 46, 54, 62,
????4, 12, 20, 28, 36, 44, 52, 60,
????2, 10, 18, 26, 34, 42, 50, 58,
????0, 8, 16, 24, 32, 40, 48, 56,
????7, 15, 23, 31, 39, 47, 55, 63,
????5, 13, 21, 29, 37, 45, 53, 61,
????3, 11, 19, 27, 35, 43, 51, 59,
????1, 9, 17, 25, 33, 41, 49, 57,
}

//終結置換表
var finalPermutation = [64]byte{
????24, 56, 16, 48, 8, 40, 0, 32,
????25, 57, 17, 49, 9, 41, 1, 33,
????26, 58, 18, 50, 10, 42, 2, 34,
????27, 59, 19, 51, 11, 43, 3, 35,
????28, 60, 20, 52, 12, 44, 4, 36,
????29, 61, 21, 53, 13, 45, 5, 37,
????30, 62, 22, 54, 14, 46, 6, 38,
????31, 63, 23, 55, 15, 47, 7, 39,
}
//代碼位置src/crypto/des/const.go

子密鑰的計算

DES初始密鑰為64位,其中8位用於奇偶校驗,實際密鑰為56位,64位初始密鑰經過PC-1密鑰置換後,生成56位串。
經PC-1置換後56位的串,分為左右兩部分,各28位,分別左移1位,形成C0和D0,C0和D0合並成56位,經PC-2置換後生成48位子密鑰K0。
C0和D0分別左移1位,形成C1和D1,C1和D1合並成56位,經PC-2置換後生成子密鑰K1。
以此類推,直至生成子密鑰K15。但註意每輪循環左移的位數,有如下規定:

var ksRotations = [16]uint8{1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1}
//代碼位置src/crypto/des/const.go

go標準庫中DES子密鑰計算的代碼如下:

func (c *desCipher) generateSubkeys(keyBytes []byte) {
????key := binary.BigEndian.Uint64(keyBytes)
????//PC-1密鑰置換,生成56位串
????permutedKey := permuteBlock(key, permutedChoice1[:])

????//56位串分左右兩部分,各28位,ksRotate為依次循環左移1位
????leftRotations := ksRotate(uint32(permutedKey >> 28))
????rightRotations := ksRotate(uint32(permutedKey<<4) >> 4)

????//生成子密鑰
????for i := 0; i < 16; i++ {
????????//合並左右兩部分,之後PC-2置換
????????pc2Input := uint64(leftRotations[i])<<28 | uint64(rightRotations[i])
????????c.subkeys[i] = permuteBlock(pc2Input, permutedChoice2[:])
????}
}
//代碼位置src/crypto/des/block.go

附go標準庫中使用的PC-1置換表和PC-2置換表:

//PC-1置換表
var permutedChoice1 = [56]byte{
????7, 15, 23, 31, 39, 47, 55, 63,
????6, 14, 22, 30, 38, 46, 54, 62,
????5, 13, 21, 29, 37, 45, 53, 61,
????4, 12, 20, 28, 1, 9, 17, 25,
????33, 41, 49, 57, 2, 10, 18, 26,
????34, 42, 50, 58, 3, 11, 19, 27,
????35, 43, 51, 59, 36, 44, 52, 60,
}

//PC-2置換表
var permutedChoice2 = [48]byte{
????42, 39, 45, 32, 55, 51, 53, 28,
????41, 50, 35, 46, 33, 37, 44, 52,
????30, 48, 40, 49, 29, 36, 43, 54,
????15, 4, 25, 19, 9, 1, 26, 16,
????5, 11, 23, 8, 12, 7, 17, 0,
????22, 3, 10, 14, 6, 20, 27, 24,
}
//代碼位置src/crypto/des/const.go

未完待續感謝關註兄弟連區塊鏈教程分享!

區塊鏈教程區塊鏈背後的信息安全2DES、3DES加密算法原理一