Go实现AES/ECB/PKCS5Padding加解密

Go语言 小铁匠 2025-08-21

在Go中实现AES/ECB/PKCS5Padding加解密需要注意以下几点:

  1. Go的标准库crypto/aes不直接支持ECB模式
  2. 需要自己实现ECB模式的加密解密逻辑
  3. PKCS5Padding实际上是PKCS7Padding的特例(块大小为8字节时)

以下是完整的实现代码:

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。

------ 本文结束 感谢阅读 ------