什么是 GBK UTF8 GB18030 GB2312
· 阅读需 2 分钟
Go 语言 实现 AES、RSA、国密算法(SM2/SM4) 的完整可运行代码,包含加密、解密、签名、验签核心功能,注释详细,新手也能直接复制使用。
github.com/tjfoc/gmsm,国内主流);base64 编码,方便传输/存储。go get github.com/tjfoc/gmsm
AES 是对称加密(加密解密用同一密钥),推荐用 CBC 模式(比 ECB 更安全,需初始化向量 IV)。
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
)
// PKCS7 补码(AES 要求明文长度为 16 字节倍数)
func pkcs7Padding(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(data, padText...)
}
// PKCS7 解补码
func pkcs7UnPadding(data []byte) ([]byte, error) {
length := len(data)
if length == 0 {
return nil, fmt.Errorf("加密数据为空")
}
// 取出最后一个字节的值,即为补码长度
padding := int(data[length-1])
return data[:length-padding], nil
}
// AESCBCEncrypt AES-CBC 加密
// key: 密钥(16/24/32 字节,对应 AES-128/AES-192/AES-256)
// iv: 初始化向量(必须 16 字节)
func AESCBCEncrypt(plainText, key, iv []byte) (string, error) {
// 1. 创建 AES 密码块
block, err := aes.NewCipher(key)
if err != nil {
return "", err
}
// 2. 补码
plainText = pkcs7Padding(plainText, block.BlockSize())
// 3. 创建 CBC 模式
mode := cipher.NewCBCEncrypter(block, iv)
// 4. 加密
cipherText := make([]byte, len(plainText))
mode.CryptBlocks(cipherText, plainText)
// 5. base64 编码返回
return base64.StdEncoding.EncodeToString(cipherText), nil
}
// AESCBCDecrypt AES-CBC 解密
func AESCBCDecrypt(cipherTextBase64 string, key, iv []byte) (string, error) {
// 1. base64 解码
cipherText, err := base64.StdEncoding.DecodeString(cipherTextBase64)
if err != nil {
return "", err
}
// 2. 创建 AES 密码块
block, err := aes.NewCipher(key)
if err != nil {
return "", err
}
// 3. 创建 CBC 解密模式
mode := cipher.NewCBCDecrypter(block, iv)
// 4. 解密
plainText := make([]byte, len(cipherText))
mode.CryptBlocks(plainText, cipherText)
// 5. 解补码
plainText, err = pkcs7UnPadding(plainText)
if err != nil {
return "", err
}
return string(plainText), nil
}
func main() {
// 测试 AES-CBC
plainText := []byte("Hello, AES Encryption!")
// 密钥(16 字节 = AES-128)
key := []byte("1234567890123456")
// IV(必须 16 字节)
iv := []byte("1234567890123456")
// 加密
cipherText, err := AESCBCEncrypt(plainText, key, iv)
if err != nil {
fmt.Printf("AES 加密失败:%v\n", err)
return
}
fmt.Printf("AES 加密结果:%s\n", cipherText)
// 解密
decryptedText, err := AESCBCDecrypt(cipherText, key, iv)
if err != nil {
fmt.Printf("AES 解密失败:%v\n", err)
return
}
fmt.Printf("AES 解密结果:%s\n", decryptedText)
}