目錄git
Des算法
發展史安全
分組密碼算法設計思想app
Des概述ide
初始置換與逆置換函數
Feistel結構工具
輪函數F學習
E擴展測試
密鑰加加密
S盒代換
P置換
密鑰編排
3Des
優缺點
分組模式
CBC
CFB
OFB
Des的Go實現
明文填充
加密
解密
結果截圖
參考
總體結構
明文進行初始置換(Initial Permutation,IP),經過密鑰編排算法將密鑰拆成16個,進行16輪迭代,最後經過逆置換獲得密文。
將輸入的64位數據塊按位從新組合,把輸出分爲L0、R0兩部分,每部分長32位。
58 |
50 |
42 |
34 |
26 |
18 |
10 |
2 |
60 |
52 |
44 |
36 |
28 |
20 |
12 |
4 |
62 |
54 |
46 |
38 |
30 |
22 |
14 |
6 |
64 |
56 |
48 |
40 |
32 |
24 |
16 |
8 |
57 |
49 |
41 |
33 |
25 |
17 |
9 |
1 |
59 |
51 |
43 |
35 |
27 |
19 |
11 |
3 |
61 |
53 |
45 |
37 |
29 |
21 |
13 |
5 |
63 |
55 |
47 |
39 |
31 |
23 |
15 |
7 |
表中的數字表明新數據中此位置的數據在原數據中的位置,即原數據塊的第58位放到新數據的第1位,第50位放到第2位,……依此類推。置換後的數據分爲L0和R0兩部分。
逆置換就是放回原位置,例如,1位置在40位置,那麼逆置換的第一個就是40,我就不一個個畫了
40 | ... |
... | ... |
因爲初始置換是公開的,沒有密碼意義。有不少DES實現都去除了,有人認爲是當時爲了更好放到DES芯片中。
按下述規則進行16次迭代,1≤i≤16
F(,
)以長度爲32比特串
做爲第一輸入,以長度爲48比特串
做爲第二個輸入,產生長度爲32比特的輸出。
32 |
1 |
2 |
3 |
4 |
5 |
4 |
5 |
6 |
7 |
8 |
9 |
8 |
9 |
10 |
11 |
12 |
13 |
12 |
13 |
14 |
15 |
16 |
17 |
16 |
17 |
18 |
19 |
20 |
21 |
20 |
21 |
22 |
23 |
24 |
25 |
24 |
25 |
26 |
27 |
28 |
29 |
28 |
29 |
30 |
31 |
32 |
1 |
將擴展爲48位,左右兩列數據是擴展的數據,擴展的數據是從相鄰位置取的一位,可理解爲循環隊列。靠近32位的位爲1,靠近1位的位爲32,其他就是下一行首或上一行末。
將的E擴展和
進行異或
使用8個S盒S1……S8,每一個Si是一個固定的4*16階矩陣,其元素取0~15之間的整數。
給定長度爲6的比特串,如Bj=b1b2b3b4b5b6,Sj(Bj)計算以下:
S盒1以下:
14 |
4 |
13 |
1 |
2 |
15 |
11 |
8 |
3 |
10 |
6 |
12 |
5 |
9 |
0 |
7 |
0 |
15 |
7 |
4 |
14 |
2 |
13 |
1 |
10 |
6 |
12 |
11 |
9 |
5 |
3 |
8 |
4 |
1 |
14 |
8 |
13 |
6 |
2 |
11 |
15 |
12 |
9 |
7 |
3 |
10 |
5 |
0 |
15 |
12 |
8 |
2 |
4 |
9 |
1 |
7 |
5 |
11 |
3 |
14 |
10 |
0 |
6 |
13 |
其餘的我就不粘貼了,都是公開的,網上能找到,這裏只是爲了舉個例子。
假如,S1的輸入Bj爲110011
P盒以下:
16 |
7 |
20 |
21 |
29 |
12 |
28 |
17 |
1 |
15 |
23 |
26 |
5 |
18 |
31 |
10 |
2 |
8 |
24 |
14 |
32 |
27 |
3 |
9 |
19 |
13 |
30 |
6 |
22 |
11 |
4 |
25 |
長度爲32比特串C=C1C2C3C4C5C6C7C8,根據上面的進行替換,原理和前面的IP同樣,就是按照P盒放原始數據的多少位,第一個就放C的第16位,依次類推,最後組合一下便可,再也不舉例。
前面是迭代加解密,接下來講下密鑰編排,密鑰編排就是經過密鑰K,得到每輪的密鑰ki,過程以下
給定64比特密鑰K,根據固定的置換PC-1來處理K獲得PC-1(K)=C0D0,其中C0和D0分別由最前和最後28比特組成。下面是PC-1,注意,不包括8,16,24,32,40,48,56和64,前面提到,這些是校驗位。
57 |
49 |
41 |
33 |
25 |
17 |
9 |
1 |
58 |
50 |
42 |
34 |
26 |
18 |
10 |
2 |
59 |
51 |
43 |
35 |
27 |
19 |
11 |
3 |
60 |
52 |
44 |
36 |
63 |
55 |
47 |
39 |
31 |
23 |
15 |
7 |
62 |
54 |
46 |
38 |
30 |
22 |
14 |
6 |
61 |
53 |
45 |
37 |
29 |
21 |
13 |
5 |
28 |
20 |
12 |
4 |
計算Ci=LSi(Ci-1)和Di=LS(Di-1),且Ki=PC-2(CiDi),LSi表示循環左移兩個或一個位置,具體地,若是i=1,2,9,16就移一個位置,不然就移兩個位置,PC-2是另外一個固定的置換。下面是PC-2
14 |
17 |
11 |
24 |
1 |
5 |
3 |
28 |
15 |
6 |
21 |
10 |
23 |
19 |
12 |
4 |
26 |
8 |
16 |
7 |
27 |
20 |
13 |
2 |
41 |
52 |
31 |
37 |
47 |
55 |
30 |
40 |
51 |
45 |
33 |
48 |
44 |
49 |
39 |
56 |
34 |
53 |
46 |
42 |
50 |
36 |
29 |
32 |
以上就是一輪中獲取Ki的過程,每輪選取密鑰K的不一樣48比特進行PC-2的置換,一樣是16個矩陣,長寬與PC-2相同,這裏就不粘貼了,否則文章太長了。
3Des3DES,顧名思義,使用三次DES算法,有兩種模式。
DES-EEE3模式:使用 P->DES加密->DES加密->DES加密->C 進行加密,使用 C->DES解密->DES解密->DES解密->P 進行解密。
DES-EDE3模式:使用 P->DES加密->DES解密->DES加密->C 進行加密,使用 C->DES解密->DES加密->DES解密->P 進行解密。
優勢:
不足:
分組密碼在加密時,明文分組的長度是固定的,而實際應用中待加密消息的數據量是不定的,數據格式多種多樣。爲了能在各類應用場合使用DES,美國在FIPS PUS 74和81中定義了DES的4種運行模式:
ECB,CBC,CFB,OFB,分組密碼工做模式描述瞭如何重複加密比較長的多個數據塊。
ECB,CBC是塊模式,CFB、OFB是流模式。ECB安全性比較差,先不學了,Go的包中也沒有。
CBC(Cipher Block Chaining, 密碼塊鏈)模式中每個分組要先和前一個分組加密後的數據進行異或操做,而後再進行加密。
加密:
解密:
CFB(Cipher Feedback, 密碼反饋)模式和CBC模式比較類似,前一個分組的密文加密後和當前分組的明文異或操做生成當前分組的密文。
加密:
解密:
注意,解密函數與加密函數一致。
OFB(Output Feedback,輸出反饋)模式與CFB模式相似,區別在於使用上一個分組的密碼序列加密生成當前分組的密碼序列。
總結
CTR模式在學AES時再說。
好,以上都沒什麼用,由於DES被破解啦!!!(看到這句話的小夥伴都快哭了)不過,增強版還能夠用,接下來就說說3DES。
Des的Go實現咱們不是使用Go語言來實現Des,已經有大神寫好了,咱們會調用就能夠了。
des包
func NewCipher(key []byte) (cipher.Block, error)
建立並返回一個使用DES算法的cipher.Block接口。
cipher包
func NewCBCEncrypter(b Block, iv []byte) BlockMode
返回一個密碼分組連接模式的、底層用b加密的BlockMode接口,初始向量iv的長度必須等於b的塊尺寸。
BlockMode的方法
CryptBlocks(dst, src []byte)
加密或解密連續的數據塊,src的尺寸必須是塊大小的整數倍,src和dst可指向同一內存地址
func NewCBCDecrypter(b Block, iv []byte) BlockMode
返回一個密碼分組連接模式的、底層用b解密的BlockMode接口,初始向量iv必須和加密時使用的iv相同。
CBC模式須要填充,解密後咱們還須要去掉填充,因爲填充什麼沒有要求,咱們就填充缺乏的長度,這樣去掉填充時就容易切片了。
func PaddingLastGroup(plainText []byte,blockSize int) []byte{ padNum := blockSize - len(plainText)%blockSize char := []byte{byte(padNum)} newPlain := bytes.Repeat(char,padNum) plainText = append(plainText,newPlain...) return plainText }
func UnpaddingLastGroup(plainText []byte) []byte { length := len(plainText) number := int(plainText[length-1]) return plainText[:length-number] }
func DesEncrypt(plainText,iv, key []byte) ([]byte,error) { if len(iv) != 8{ _, file, line, _ := runtime.Caller(0) return nil,util.Error(file,line+1,errors.IvError) } block, err :=des.NewCipher(key) if err != nil{ _, file, line, _ := runtime.Caller(0) return nil,util.Error(file,line+1,errors.DesKeyError) } // padding plainText newText := util.PaddingLastGroup(plainText,des.BlockSize) // Create a CBC interface blockMode := cipher.NewCBCEncrypter(block,iv) // use same one to save space blockMode.CryptBlocks(newText,newText) return newText,nil }
func DesDecrypt(cipherText,iv,key []byte) ([]byte,error) { if len(iv) != 8{ _, file, line, _ := runtime.Caller(0) return nil,util.Error(file,line+1,errors.IvError) } block, err :=des.NewCipher(key) if err != nil{ _, file, line, _ := runtime.Caller(0) return nil,util.Error(file,line+1,errors.DesKeyError) } // Create a CBC interface blockMode := cipher.NewCBCDecrypter(block,iv) plainText := make([]byte,len(cipherText)) blockMode.CryptBlocks(plainText,cipherText) return util.UnpaddingLastGroup(plainText),nil }
部分測試代碼
iv := []byte("12345678") key := []byte("ladykill") plainText := []byte("hellocrypto") cipherText,err := DesEncrypt(plainText,iv,key) if err != nil{ fmt.Println(err) os.Exit(0) } fmt.Printf("加密後:%s\n",string(cipherText)) decryText,_ := DesDecrypt(cipherText,iv,key) fmt.Printf("解密後:%s\n",string(decryText))
3Des只須要建立時使用des.NewTripleDESCipher(key)便可。
代碼我放到了gitee上:https://gitee.com/frankyu365/gocrypto
您能夠查看倉庫Readme文檔或Go-包管理(管理工具對比及go mod的使用)來進行安裝
《現代密碼學教程 谷利澤,楊義先等》
Go標準庫-crypto/des
Go標準庫-crypto/cipher
更多Go相關內容:Go-Golang學習總結筆記
有問題請下方評論,轉載請註明出處,並附有原文連接,謝謝!若有侵權,請及時聯繫。·