網站首頁 編程語言 正文
前言
本文包含如下兩個內容:
AES加密介紹及實現原理
Go實現AES加密和解密工具
AES加密介紹及實現原理
AES( advanced encryption standard)使用相同密鑰進行加密和解密,也就是對稱加密。其他的對稱加密如DES,由于DES密鑰長度只有56位如今的算力甚至可以在5分鐘內破解,而AES最高級別達到了256位密鑰長度,如果采用窮舉法,目前來看AES是一種”無法“被破解的加密存在。
AES用在哪里
如果你正在瀏覽本文,那么你就在使用AES(https協議中一部分使用了對稱加密)。
- 綠色上網:通過加密安全地連接到另一臺搬石頭砸腳的服務器。
- 無線網絡WIFI:和WAP2一起使用。
- 應用程序:wechat、JD、Alipay等使用 AES 加密照片和消息或支付信息。
- 存檔和壓縮工具:7z、WinZip 和 RAR。
- 操作系統組件:一些操作系統組件(如文件系統)使用高級加密標準來確保安全性。
- 編程語言庫:?Go、Python 和 C++ 等編碼庫實現了的AES加密(等會使用到)。
AES加密是如何實現的
參考:
what-is-the-aes-algorithm?
What is AES encryption and how does it work?
Block cipher mode of operation
從宏觀上來看AES加密過程中的一輪(根據不同的密鑰長度,輪數不一樣,下面會說到)如下:
1.數據分塊
首先把明文按照128bit拆分成若干個明文塊(圖上黃色塊),一個字節包含 8 位,布局為 4×4矩陣(上圖黃色部分),對最后一塊填充至128bit,填充方式有PKCS7Padding(采用)/PKCS5Padding/ZeroPadding,無論咋填充最后解密時都要去除這些多余的填充。
2.密鑰擴展
AES通過Rijndael's key schedule?將密鑰被擴展為 (n+1) 個密鑰,其中 n 是加密過程中要遵循的輪數。AES每個標準規定了所要加密的輪數,對于128位密鑰,輪數是 10,要生成的密鑰個數為 10+1,總共 11 個密鑰。
標準 | 密鑰長度 | 輪數 | 分組長度 |
---|---|---|---|
AES-128 | 128位(16字節) | 10 | 128位(16字節) |
AES-192 | 192位(24字節) | 12 | 128位(16字節) |
AES-256 | 256位(32字節) | 14 | 128位(16字節) |
每一輪所要做的包括:字節替代(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)、加輪密鑰(AddRoundKey)
3.字節替代(SubBytes)
每輪開始,首先進行SubBytes,字節根據預定義的?Rijndael S-box(可以簡單認為是一個轉換表)規定的規則進行替換。對a[i,j]中的每個字節進行一次轉換后得到b[i,j]
4.行移位(ShiftRows)
對上一步得到矩陣進行ShiftRows,第一行不變,第二行移動1位,第三行2位,第四行3位。
5.列混淆(MixColumns)
再對矩陣的每一列和修補矩陣fixed matrix的二維常量數組做矩陣相乘,得到對應的輸出列。
6.加輪密鑰(AddRoundKey)
先將擴展密鑰Kn排列成4×4矩陣,然后讓輸入數組的每一個字節a[i,j]與密鑰對應位置的字節k[i,j]異或一次,得到輸出b[i,j]。最后一輪不參與AddRoundKey
經過如上的10輪操作之后,得到了一個明文塊的加密字符。解密則進行反向加密。
AES加密模式
ECB
在上面加密過程中每一個明文塊都是獨立進行加密的,簡單且高效,但是如果一個段數據存在相關的明文塊,則加密后的密文也會相同,對安全性也有一定影響。
CBC
CBC加密模式如下圖所示,初始向量IV和明文異或,每個塊的密文作為后續塊的“向量”,讓每一個密文獨一無二。我們待會采用這種模式。
Go實現AES加密工具scode
ok,上面大致了解AES加密是如何工作起來的,接下來通過Go中的crypto/aes和crypto/cipher包實現的AES加密解密工具。
PKCS7Padding將待補足字節數作為填充的字節
// pkcs7Padding 填充 func pkcs7Padding(data []byte, blockSize int) []byte { //判斷缺少幾位長度。最少1,最多 blockSize padding := blockSize - len(data)%blockSize //補足位數。把切片[]byte{byte(padding)}復制padding個 padText := bytes.Repeat([]byte{byte(padding)}, padding) return append(data, padText...) } // pkcs7UnPadding 移除 func pkcs7UnPadding(data []byte) ([]byte, error) { length := len(data) if length == 0 { return nil, errors.New("加密字符串錯誤!") } //獲取填充的個數 unPadding := int(data[length-1]) return data[:(length - unPadding)], nil }
使用 cipher的CBC模式對block加密和解密
// AesEncrypt 加密 func AesEncrypt(data []byte, key []byte) ([]byte, error) { // NewCipher creates and returns a new cipher.Block. The key argument should be the AES key, either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256. block, err := aes.NewCipher(key) if err != nil { return nil, err } //判斷加密快的大小 blockSize := block.BlockSize() //填充 encryptBytes := pkcs7Padding(data, blockSize) //初始化加密數據接收切片 crypted := make([]byte, len(encryptBytes)) //使用cbc加密模式 blockMode := cipher.NewCBCEncrypter(block, key[:blockSize]) //執行加密 blockMode.CryptBlocks(crypted, encryptBytes) return crypted, nil } // AesDecrypt 解密 func AesDecrypt(data []byte, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } //獲取塊的大小 blockSize := block.BlockSize() //使用cbc blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) //初始化解密數據接收切片 crypted := make([]byte, len(data)) //執行解密 blockMode.CryptBlocks(crypted, data) //去填充 crypted, err = pkcs7UnPadding(crypted) if err != nil { return nil, err } return crypted, nil }
循環從文件中讀取100mb源數據用于加密后將密文寫入文件,解密則讀取密文解密后將源數據寫入文件。
func EncryptFile(fileName string) (err error) { f, err := os.Open(fileName) if err != nil { fmt.Println("未找到文件") return } defer f.Close() fInfo, _ := f.Stat() fLen := fInfo.Size() fmt.Println("待處理文件大小:", fLen) maxLen := 1024 * 1024 * 100 //100mb 每 100mb 進行加密一次 var forNum int64 = 0 getLen := fLen if fLen > int64(maxLen) { getLen = int64(maxLen) forNum = fLen / int64(maxLen) fmt.Println("需要加密次數:", forNum+1) } // encryptd to file ff, err := os.OpenFile("en_"+fileName, os.O_RDWR|os.O_CREATE, 0666) if err != nil { fmt.Println("文件寫入錯誤") return err } defer ff.Close() //循環加密,并寫入文件 for i := 0; i < int(forNum+1); i++ { a := make([]byte, getLen) n, err := f.Read(a) if err != nil { fmt.Println("文件讀取錯誤") return err } getByte, err := EncryptByAes(a[:n]) if err != nil { fmt.Println("加密錯誤") return err } getBytes := append([]byte(getByte), []byte("\n")...) //寫入 buf := bufio.NewWriter(ff) buf.WriteString(string(getBytes[:])) buf.Flush() } ffInfo, _ := ff.Stat() fmt.Printf("加密后文件為:%s,文件大小為:%v Byte \n", ffInfo.Name(), ffInfo.Size()) return nil }
參考:Golang實現AES加密和解密的示例代碼
通過cobra添加命令后,創建命令的匿名函數
func(cmd *cobra.Command, args []string) { copy(PwdKey, readPass()) Pwd := []byte("csgo!gogo") if ByteSliceEqual(PwdKey, Pwd) { //16字節key PwdKey = append(PwdKey, 7, 3, 5, 5, 6, 0, 8) if err := DecryptFile(args[0]); err != nil { panic(err) } } else { fmt.Println("密碼錯誤") os.Exit(1) } }
使用方式看起來如下:
scode工具包含2個命令encode和decode,解密文件需要密碼。
# ./scode encode xpower.tar.gz 待處理文件大小: 3397 加密后文件為:en_xpower.tar.gz,文件大小為:4545 Byte # ./scode decode en_xpower.tar.gz ENTER PASSWORD: 密碼錯誤 # ./scode decode en_xpower.tar.gz ENTER PASSWORD: 待處理文件大小: 4545 解密后文件為:de_en_xpower.tar.gz,文件大小為:3159 Byte
完整代碼:source
原文鏈接:https://www.cnblogs.com/qsing/p/16263693.html
相關推薦
- 2022-06-14 web項目中golang性能監控解析_Golang
- 2022-04-19 css隱藏??元素的幾種方式
- 2022-07-21 toggleRowSelection失效的2個原因
- 2022-07-30 分布式session的問題(使用SpringSession和redis解決)
- 2022-10-12 Nginx?504?Gateway?Time-out的兩種最新解決方案_nginx
- 2022-10-27 詳解Python中enumerate函數的使用_python
- 2023-11-24 局部路由守衛path守衛
- 2021-12-06 linux下ceph分布式安裝使用教程_Linux
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支