生活随笔
收集整理的這篇文章主要介紹了
golang中的对称加密
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
概念
按位異或
-
第一步需要將數據轉換為二進制
-
按位異或操作符: ^
-
兩個標志位進行按位異或操作:
-
舉例:
1 0 0 0 ----> 8
1 0 1 1 ----> 11
-----------------------按位異或一次
0 0 1 1 ----> 3
1 0 1 1 ----> 11
-----------------------按位異或兩側
1 0 0 0 -----> 8
=================================
a = 8
b = 11
a 和 b按位異或1次 ==> 加密
得到的結果再次和 b 按位異或 ===> 解密
ECB - Electronic Code Book, 電子密碼本模式
- 特點: 簡單, 效率高, 密文有規律, 容易被破解
- 最后一個明文分組必須要填充
- des/3des -> 最后一個分組填充滿8字節
- aes -> 最后一個分組填充滿16字節
- 不需要初始化向量
CBC - Cipher Block Chaining, 密碼塊鏈模式
- 特點: 密文沒有規律, 經常使用的加密方式
- 最后一個明文分組需要填充
- des/3des -> 最后一個分組填充滿8字節
- aes -> 最后一個分組填充滿16字節
- 需要一個初始化向量 - 一個數組
- 數組的長度: 與明文分組相等
- 數據來源: 負責加密的人的提供的
- 加解密使用的初始化向量值必須相同
CFB - Cipher FeedBack, 密文反饋模式
- 特點: 密文沒有規律, 明文分組是和一個數據流進行的按位異或操作, 最終生成了密文
- 需要一個初始化向量 - 一個數組
- 數組的長度: 與明文分組相等
- 數據來源: 負責加密的人的提供的
- 加解密使用的初始化向量值必須相同
- 不需要填充
OFB - Output-Feedback, 輸出反饋模式
- 特點: 密文沒有規律, 明文分組是和一個數據流進行的按位異或操作, 最終生成了密文
- 需要一個初始化向量 - 一個數組
- 數組的長度: 與明文分組相等
- 數據來源: 負責加密的人的提供的
- 加解密使用的初始化向量值必須相同
- 不需要填充
CTR - CounTeR, 計數器模式
- 特點: 密文沒有規律, 明文分組是和一個數據流進行的按位異或操作, 最終生成了密文
- 不需要初始化向量
- go接口中的iv可以理解為隨機數種子, iv的長度 == 明文分組的長度
- 不需要填充
最后一個明文分組的填充
- 使用cbc, ecb需要填充
- 要求:
- 明文分組中進行了填充, 然后加密
- 解密密文得到明文, 需要把填充的字節刪除
- 使用 ofb, cfb, ctr不需要填充
初始化向量 - IV
- ecb, ctr模式不需要初始化向量
- cbc, ofc, cfb需要初始化向量
- 初始化向量的長度
- des/3des -> 8字節
- aes -> 16字節
- 加解密使用的初始化向量相同
實現
des
3des
aes
# 加密流程:1. 創建一個底層使用des/3des/aes的密碼接口"crypto/des"func NewCipher(key []byte) (cipher.Block, error) # -- desfunc NewTripleDESCipher(key []byte) (cipher.Block, error) # -- 3des"crypto/aes"func NewCipher(key []byte) (cipher.Block, error) # == aes2. 如果使用的是cbc/ecb分組模式需要對明文分組進行填充3. 創建一個密碼分組模式的接口對象- cbcfunc NewCBCEncrypter(b Block, iv []byte) BlockMode # 加密- cfbfunc NewCFBEncrypter(block Block, iv []byte) Stream # 加密- ofb- ctr4. 加密, 得到密文
import ("bytes""crypto/aes""crypto/cipher""crypto/des""fmt"
)//des的CBC加密
//編寫填充函數,如果最后一個分組字節不夠,填充
//...字節數剛好合適,添加一個新分組
//填充個的字節的值==缺少的字節數
func paddingLastGroup(plainText []byte, bloclsize int) []byte {//1. 求出最后一個組中剩余的字節數padNum := bloclsize - (len(plainText) % bloclsize)//2. 創建一個新的切片, 長度==padNum, 每個字節值byte(padNum)char := []byte{byte(padNum)} //切片長度是1//切片創建并且重復多少次newPlain := bytes.Repeat(char, padNum)//3. newPlain數組追加到原始明文的后面newText := append(plainText, newPlain...)return newText
}//去掉填充的數據
func unPaddingLastGrooup(plainText []byte) []byte {//1. 拿去切片中的最后一個字節length := len(plainText)lastChar := plainText[length-1]number := int(lastChar) //尾部填充的字節數return plainText[:length-number]
}//des加密
func desEncrypt(plainText, key []byte) []byte {//1. 建一個底層使用des的密碼接口block, err := des.NewCipher(key)if err != nil {panic(err)}//2. 明文填充newText := paddingLastGroup(plainText, block.BlockSize())//3. 創建一個使用cbc分組接口iv := []byte("12345678") //8字節blockMode := cipher.NewCBCEncrypter(block, iv)//4. 加密cipherText := make([]byte, len(newText))blockMode.CryptBlocks(cipherText, newText)//也可以這樣,他加密過會把newText的值覆蓋過去,然后返回newText就可以//blockMode.CryptBlocks(newText, newText)return cipherText
}// des解密
func desDecrypt(cipherText, key []byte) []byte {// 1. 建一個底層使用des的密碼接口block, err := des.NewCipher(key)if err != nil {panic(err)}// 2. 創建一個使用cbc模式解密的接口iv := []byte("12345678")blockMode := cipher.NewCBCDecrypter(block, iv)// 3. 解密blockMode.CryptBlocks(cipherText, cipherText)// 4. cipherText現在存儲的是明文, 需要刪除加密時候填充的尾部數據plainText := unPaddingLastGrooup(cipherText)return plainText
}// aes加密, 分組模式ctr
func aesEncrypt(plainText, key []byte) []byte {// 1. 建一個底層使用aes的密碼接口block, err := aes.NewCipher(key)if err != nil {panic(err)}// 2. 創建一個使用ctr分組接口iv := []byte("12345678WHZdefgh")stream := cipher.NewCTR(block, iv)// 4. 加密cipherText := make([]byte, len(plainText))stream.XORKeyStream(cipherText, plainText)return cipherText
}// des解密
func aesDecrypt(cipherText, key []byte) []byte {// 1. 建一個底層使用des的密碼接口block, err := aes.NewCipher(key)if err != nil {panic(err)}// 2. 創建一個使用ctr模式解密的接口iv := []byte("12345678WHZdefgh")stream := cipher.NewCTR(block, iv)// 3. 解密stream.XORKeyStream(cipherText, cipherText)return cipherText
}//測試文件
func main() {fmt.Println("des 加解密")key := []byte("1234abEd")src := []byte("特點: 密文沒有規律, 明文分組是和一個數據流進行的按位異或操作, 最終生成了密文")cipherText := desEncrypt(src, key)plainText := desDecrypt(cipherText, key)fmt.Printf("解密之后的數據: %s\n", string(plainText))fmt.Println("aes 加解密 ctr模式 ... ")key1 := []byte("1234abdd12345678")cipherText = aesEncrypt(src, key1)plainText = aesDecrypt(cipherText, key1)fmt.Printf("解密之后的數據: %s\n", string(plainText))
}
總結
-
對稱加密中的公開的加密算法
-
des
-
3des
-
aes
- 分組長度: 16字節
- 秘鑰長度: 16字節, 24字節, 32字節
-
對稱加密的分組模式
總結
以上是生活随笔為你收集整理的golang中的对称加密的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。