對稱式加密演算法,即加密和解密使用一樣的密鑰的加解密演算法。
分組密碼(block cipher),是每次只能處理特定長度的一塊(block)資料的一類加解密演算法。
目前常見的對稱式加密演算法DES、3DES、AES都是屬於分組密碼。
背景
Golang沒有像PHP那樣提供一個現成的aes加密函數,不過標準庫裡有crypto,利用裡面的aes等可以自己封裝個加密函數,不過需要理解下整個加解密的過程和原理
AES加密詳解
1. 參考文章golang 中AES加密詳解
2. 這裡使用的是AES加密中的CBC模式,塊加密需要劃分成整數長度相等個訊息塊不斷加密(串列),分組長度是固定128位,但密鑰的長度可以使用128位,192位或者256位(這裡指的是bit),即密鑰16,24,32長度對應AES-128, AES-192, AES-256。
3.初始向量要求隨機,但不需要保密。
代碼
自己研究代碼比較清晰,根據golang標準庫AES執行個體代碼,再參考網上的PKCS7填充,最後進行base64的編碼(因為加密後有些字元不可見)。最後Encrypt和Dncrypt兩個就是AES加解密(CBC模式,PKCS7填充)封裝後的函數,密鑰位元限定16,24,32(要注意的是密鑰無論多少,blocksize都是固定16)
package encryptimport ( "bytes" "crypto/aes" "io" "crypto/rand" "crypto/cipher" "encoding/base64")/*CBC加密 按照golang標準庫的例子代碼不過裡面沒有填充的部分,所以補上*///使用PKCS7進行填充,IOS也是7func PKCS7Padding(ciphertext []byte, blockSize int) []byte { padding := blockSize - len(ciphertext) % blockSize padtext := bytes.Repeat([]byte{byte(padding)}, padding) return append(ciphertext, padtext...)}func PKCS7UnPadding(origData []byte) []byte { length := len(origData) unpadding := int(origData[length-1]) return origData[:(length - unpadding)]}//aes加密,填充秘鑰key的16位,24,32分別對應AES-128, AES-192, or AES-256.func AesCBCEncrypt(rawData,key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { panic(err) } //填充原文 blockSize := block.BlockSize() rawData = PKCS7Padding(rawData, blockSize) //初始向量IV必須是唯一,但不需要保密 cipherText := make([]byte,blockSize+len(rawData)) //block大小 16 iv := cipherText[:blockSize] if _, err := io.ReadFull(rand.Reader,iv); err != nil { panic(err) } //block大小和初始向量大小一定要一致 mode := cipher.NewCBCEncrypter(block,iv) mode.CryptBlocks(cipherText[blockSize:],rawData) return cipherText, nil}func AesCBCDncrypt(encryptData, key []byte) ([]byte,error) { block, err := aes.NewCipher(key) if err != nil { panic(err) } blockSize := block.BlockSize() if len(encryptData) < blockSize { panic("ciphertext too short") } iv := encryptData[:blockSize] encryptData = encryptData[blockSize:] // CBC mode always works in whole blocks. if len(encryptData)%blockSize != 0 { panic("ciphertext is not a multiple of the block size") } mode := cipher.NewCBCDecrypter(block, iv) // CryptBlocks can work in-place if the two arguments are the same. mode.CryptBlocks(encryptData, encryptData) //解填充 encryptData = PKCS7UnPadding(encryptData) return encryptData,nil}func Encrypt(rawData,key []byte) (string,error) { data, err:= AesCBCEncrypt(rawData,key) if err != nil { return "",err } return base64.StdEncoding.EncodeToString(data),nil}func Dncrypt(rawData string,key []byte) (string,error) { data,err := base64.StdEncoding.DecodeString(rawData) if err != nil { return "",err } dnData,err := AesCBCDncrypt(data,key) if err != nil { return "",err } return string(dnData),nil}
參考:
- golang 中AES加密詳解