示例 #3 Go 1.26.3 linux/amd64 AES-128-CBC 加密、AES-128-CBC 解密示例(搬来即用)
- 该示例适用于 AES-128-CBC、AES-192-CBC、AES-256-CBC 等系列的加密算法。
- 在 Go 语言中,AES 加密算法对秘钥的长度要求很严格,少一个字节或多一个字节都会直接 panic。
- 在 Go 语言中 AES 秘钥的长度(16/24/32)决定不同的加密强度。以CBC加密模式举例,例如:秘钥长度16字节(128位密钥),对应 AES-128-CBC;秘钥长度24字节(192位密钥),对应 AES-192-CBC;秘钥长度32字节(256位密钥),对应 AES-256-CBC。
- 非常重要:数据填充一定要用 PKCS7Padding,其他过时的填充方法,应该及时更换。
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"errors"
"fmt"
"io"
"log"
)
func main() {
// 加密的秘钥
key := []byte("secretkey0123456")
// 加密的内容
plaintext := []byte("message to be encrypted")
// 生成随机IV值
iv := make([]byte, 16)
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
log.Fatal(err)
}
// 获取cipher.block
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
// 明文长度补位
plaintext = PKCS7Padding(plaintext, block.BlockSize())
if len(plaintext)%aes.BlockSize != 0 {
return nil, errors.New("plaintext is not a multiple of the block size")
}
ciphertext := make([]byte, len(plaintext))
mode := cipher.NewCBCEncrypter(block, iv)
// 把明文换算成密文
mode.CryptBlocks(ciphertext, plaintext)
// ciphertext 是二进制数据
// 使用base64编码输出加密的结果
fmt.Printf("%s\n", base64.StdEncoding.EncodeToString(ciphertext))
// 解密代码段
// 实战中,务必保存IV和key两个值
mode = cipher.NewCBCDecrypter(block, iv)
// 把密文还原成明文
mode.CryptBlocks(ciphertext, ciphertext)
// 去掉补位内容
ciphertext, _ = PKCS7Unpadding(ciphertext)
fmt.Printf("%s\n", ciphertext)
}
// 采用 PKCS7Padding 补位
func PKCS7Padding(plaintext []byte, blockSize int) []byte {
padding := blockSize - len(plaintext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(plaintext, padtext...)
}
// 去掉 PKCS7Padding 补位的内容
func PKCS7Unpadding(plaintext []byte) ([]byte, error) {
length := len(plaintext)
unpadding := int(plaintext[length-1])
if length-unpadding < 0 {
return nil, errors.New("PKCS7Unpadding error")
}
return plaintext[:(length - unpadding)], nil
}
AES-128-CBC 加密的结果(ciphertext 变量的值。因为IV是随机值,因此大家得到的结果不同):yk3s53MmpYLL/2SyHGnEdVcblNwwxnFVUy3kJVPi268=
AES-128-CBC 解密的结果:message to be encrypted