在Go中实现AES/ECB/PKCS5Padding加解密需要注意以下几点:
crypto/aes
不直接支持ECB模式以下是完整的实现代码:
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"errors"
"fmt"
"log"
)
// PKCS5Padding 实现PKCS5/PKCS7填充
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
// PKCS5UnPadding 去除PKCS5/PKCS7填充
func PKCS5UnPadding(origData []byte) ([]byte, error) {
length := len(origData)
if length == 0 {
return nil, errors.New("pkcs5UnPadding: ciphertext is empty")
}
unpadding := int(origData[length-1])
if unpadding > length {
return nil, errors.New("pkcs5UnPadding: invalid unpadding size")
}
return origData[:(length - unpadding)], nil
}
// AESECBEncrypt ECB模式加密
func AESECBEncrypt(plaintext []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
// 检查密钥长度
if len(key) != 16 && len(key) != 24 && len(key) != 32 {
return nil, errors.New("aesECBEncrypt: invalid key size")
}
// 对数据进行PKCS5填充
plaintext = PKCS5Padding(plaintext, block.BlockSize())
// ECB模式加密
ciphertext := make([]byte, len(plaintext))
for len(plaintext) > 0 {
block.Encrypt(ciphertext, plaintext[:block.BlockSize()])
plaintext = plaintext[block.BlockSize():]
ciphertext = ciphertext[block.BlockSize():]
}
return ciphertext, nil
}
// AESECBDecrypt ECB模式解密
func AESECBDecrypt(ciphertext []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
// 检查密钥长度
if len(key) != 16 && len(key) != 24 && len(key) != 32 {
return nil, errors.New("aesECBDecrypt: invalid key size")
}
// 检查密文长度是否为块大小的整数倍
if len(ciphertext)%block.BlockSize() != 0 {
return nil, errors.New("aesECBDecrypt: ciphertext is not a multiple of the block size")
}
// ECB模式解密
plaintext := make([]byte, len(ciphertext))
for len(ciphertext) > 0 {
block.Decrypt(plaintext, ciphertext[:block.BlockSize()])
ciphertext = ciphertext[block.BlockSize():]
plaintext = plaintext[block.BlockSize():]
}
// 去除PKCS5填充
return PKCS5UnPadding(plaintext)
}
func main() {
// 测试数据
key := []byte("1234567890123456") // 16字节密钥(AES-128)
plaintext := []byte("Hello, AES ECB mode with PKCS5Padding!")
fmt.Printf("Original: %s\n", plaintext)
// 加密
ciphertext, err := AESECBEncrypt(plaintext, key)
if err != nil {
log.Fatalf("Encryption failed: %v", err)
}
fmt.Printf("Encrypted: %x\n", ciphertext)
// 解密
decrypted, err := AESECBDecrypt(ciphertext, key)
if err != nil {
log.Fatalf("Decryption failed: %v", err)
}
fmt.Printf("Decrypted: %s\n", decrypted)
}
注意事项
1、ECB模式不推荐用于加密大量数据或安全性要求高的场景,因为它没有混淆效果,相同的明文块会生成相同的密文块。
2、在实际应用中,建议使用更安全的模式如CBC、GCM等,并添加认证机制。
3、密钥长度应为16(AES-128)、24(AES-192)或32字节(AES-256)。
4、此实现是基础的ECB模式,没有处理初始化向量(IV),因为ECB模式本身不需要IV。