最近有一個需求需要在golang中實現AES ECB模式的加密和解密, 看了一下官方文檔和相關資料發現golang 官方包並沒有完善的實現,於是自己嘗試寫了一個,本文中的AES算法是基於ECB模式,關於AES算法的幾種模式原理大家可以去百度搜索一下,集中模式如下。
1. 電碼本模式(Electronic Codebook Book (ECB))
2.密碼分組鏈接模式(Cipher Block Chaining (CBC))
3.計算器模式(Counter (CTR))
4.密碼反饋模式(Cipher FeedBack (CFB))
5.輸出反饋模式(Output FeedBack (OFB))
我這裏採用的ECB加密基本原理是將明文切分成若干相同的小段,然後對每一段進行加密和解密,最後組合就是最終的結果,AES算法有AES-128、AES-192、AES-256三種,分別對應的key是 16、24、32字節長度,同樣對應的加密解密區塊長度BlockSize也是16、24、32字節長度。
下面貼上我的實現代碼:
package main
import (
"bytes"
"crypto/aes"
"fmt"
)
//AES ECB模式的加密解密
type AesTool struct {
//128 192 256位的其中一個 長度 對應分別是 16 24 32字節長度
Key []byte
BlockSize int
}
func NewAesTool(key []byte, blockSize int) *AesTool {
return &AesTool{Key: key, BlockSize: blockSize}
}
func (this *AesTool) padding(src []byte) []byte {
//填充個數
paddingCount := aes.BlockSize - len(src)%aes.BlockSize
if paddingCount == 0 {
return src
} else {
//填充數據
return append(src, bytes.Repeat([]byte{byte(0)}, paddingCount)...)
}
}
//unpadding
func (this *AesTool) unPadding(src []byte) []byte {
for i := len(src) - 1; ; i-- {
if src[i] != 0 {
return src[:i+1]
}
}
return nil
}
func (this *AesTool) Encrypt(src []byte) ([]byte, error) {
//key只能是 16 24 32長度
block, err := aes.NewCipher([]byte(this.Key))
if err != nil {
return nil, err
}
//padding
src = this.padding(src)
//返回加密結果
encryptData := make([]byte, len(src))
//存儲每次加密的數據
tmpData := make([]byte, this.BlockSize)
//分組分塊加密
for index := 0; index < len(src); index += this.BlockSize {
block.Encrypt(tmpData, src[index:index+this.BlockSize])
copy(encryptData, tmpData)
}
return encryptData, nil
}
func (this *AesTool) Decrypt(src []byte) ([]byte, error) {
//key只能是 16 24 32長度
block, err := aes.NewCipher([]byte(this.Key))
if err != nil {
return nil, err
}
//返回加密結果
decryptData := make([]byte, len(src))
//存儲每次加密的數據
tmpData := make([]byte, this.BlockSize)
//分組分塊加密
for index := 0; index < len(src); index += this.BlockSize {
block.Decrypt(tmpData, src[index:index+this.BlockSize])
copy(decryptData, tmpData)
}
return this.unPadding(decryptData), nil
}
//測試padding unpadding
func TestPadding() {
tool := NewAesTool([]byte{}, 16)
src := []byte{1, 2, 3, 4, 5}
src = tool.padding(src)
fmt.Println(src)
src = tool.unPadding(src)
fmt.Println(src)
}
//測試AES ECB 加密解密
func TestEncryptDecrypt() {
key := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}
blickSize := 16
tool := NewAesTool(key, blickSize)
encryptData, _ := tool.Encrypt([]byte("32334erew32"))
fmt.Println(encryptData)
decryptData, _ := tool.Decrypt(encryptData)
fmt.Println(string(decryptData))
}
func main() {
fmt.Println("Padding Test........")
TestPadding()
fmt.Println("AES ECB加密解密測試........")
TestEncryptDecrypt()
}