Go语言AES-CBC对称加密实战:原理、代码与注意事项

落日邮差
落日邮差
发布时间:2026-10-15| 5人浏览过
原创

针对项目中手机号、身份证号等敏感接口的传输安全,本文详细介绍了如何在 Go 语言中使用 AES 算法的 CBC 模式进行对称加密。通过封装 `AESCbcEncrypt` 和 `AESCbcDecrypt` 函数,结合 PKCS7 填充标准与随机 IV 机制,实现高效且安全的密文交互方案。

AES 对称加密基础

对称加密指加密和解密使用同一个密钥,相比非对称加密(公钥/私钥对),其计算效率更高,适合大数据量或高频调用场景。在 Go 的标准库中,我们主要关注 AES(Advanced Encryption Standard)算法。

AES 支持 128、192、256 三种密钥长度,对应的块大小固定为 128 bits(16 字节)。虽然 Golang 的 `crypto/aes` 包支持所有长度,但在实际工程中,**AES-128(16 byte 密钥)**因性能与安全的平衡而被广泛采用。本文示例将基于 AES-128 进行演示。

CBC 模式工作原理

AES 是分组密码,需配合工作模式使用。其中 CBC(Cipher Block Chaining,密文反馈模式)通过将前一个密文块与当前明文块异或后再加密,有效隐藏了明文的统计规律,比 ECB 模式更安全。

第1步:准备加密块与密钥处理

首先创建 Cipher 对象,并对传入的密钥进行处理。若密钥长度超过 16 字节,默认截取前 16 字节以保证兼容性;若不足,在实际生产环境中建议报错或补充填充,此处为简化演示直接取前缀。

func AESCbcEncrypt(secretKey, src string) string {
	key := []byte(secretKey)
	if len(key) > 16 {
		key = key[:16]
	}
	plaintext := []byte(src)
	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}
	// ...后续步骤见下文

第2步:数据填充(PKCS7)

CBC 模式要求输入数据的长度必须是块大小(16字节)的整数倍。当明文长度不足时,需进行填充。这里采用标准的 PKCS7 填充方式,即补入的字节值为所缺少的字节数。

func Padding(plainText []byte, blockSize int) []byte {
	padding := blockSize - len(plainText)%blockSize
	char := []byte{byte(padding)}
	newPlain := bytes.Repeat(char, padding)
	return append(plainText, newPlain...)
}

第3步:生成随机初始化向量(IV)

IV 用于打破相同明文产生相同密文的规律。**每次加密必须生成不同的随机 IV**,但加密和解密时必须使用相同的 IV。在 CBC 模式下,通常将生成的 IV 放在密文的最前面一并传输。

	// 预留空间给IV
	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		panic(err)
	}

第4步:执行加密操作

使用 `cipher.NewCBCEncrypter` 创建加密器,并将填充后的明文填入剩余空间进行加密。最后对包含 IV 和密文的整体数据进行 Base64 编码,便于在网络传输中作为字符串处理。

	mode := cipher.NewCBCEncrypter(block, iv)
	mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
	return base64.StdEncoding.EncodeToString(ciphertext)

完整加密实现

结合上述步骤,完整的 Go 语言 AES-CBC 加密函数如下:

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
	"errors"
	"io"
)

func AESCbcEncrypt(secretKey, src string) (string, error) {
	key := []byte(secretKey)
	if len(key) > 16 {
		key = key[:16]
	}
	// 确保密钥长度足够
	if len(key) < 16 {
		return "", errors.New("key too short")
	}

	plaintext := []byte(src)
	block, err := aes.NewCipher(key)
	if err != nil {
		return "", err
	}

	plaintext = Padding(plaintext, block.BlockSize())
	if len(plaintext)%aes.BlockSize != 0 {
		return "", errors.New("plaintext is not a multiple of the block size")
	}

	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		return "", err
	}

	mode := cipher.NewCBCEncrypter(block, iv)
	mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)

	return base64.StdEncoding.EncodeToString(ciphertext), nil
}

解密流程与实现

解密是加密的逆过程。首先解码 Base64 数据,分离出 IV 和真实密文,验证密文长度合法性后,使用 `NewCBCDecrypter` 进行解密,最后去除填充。

第1步:Base64 解码与结构分离

func AESCbcDecrypt(secretKey, src string) (string, error) {
	key := []byte(secretKey)
	if len(key) > 16 {
		key = key[:16]
	}
	if len(key) < 16 {
		return "", errors.New("key too short")
	}

	ciphertext, err := base64.StdEncoding.DecodeString(src)
	if err != nil {
		return "", err
	}

第2步:提取 IV 并验证长度

	if len(ciphertext) < aes.BlockSize {
		return "", errors.New("ciphertext too short")
	}
	iv := ciphertext[:aes.BlockSize]
	ciphertext = ciphertext[aes.BlockSize:] // 去掉IV头
	if len(ciphertext)%aes.BlockSize != 0 {
		return "", errors.New("ciphertext is not a multiple of the block size")
	}

第3步:解密与去填充

	block, err := aes.NewCipher(key)
	if err != nil {
		return "", err
	}

	mode := cipher.NewCBCDecrypter(block, iv)
	mode.CryptBlocks(ciphertext, ciphertext)

	ciphertext = UnPadding(ciphertext)
	return string(ciphertext), nil
}

取消填充逻辑

根据最后一个字节的值确定填充长度,截取原始数据:

func UnPadding(plainText []byte) []byte {
	length := len(plainText)
	if length == 0 {
		return plainText
	}
	padding := int(plainText[length-1])
	if padding > length {
		return plainText
	}
	return plainText[:length-padding]
}

总结

本文展示了在 Go 语言中通过 `crypto/aes` 和 `crypto/cipher` 标准库实现 AES-CBC 对称加密的完整路径。关键在于:1. 严格处理密钥长度;2. 正确实现 PKCS7 填充;3. 确保 IV 的唯一性与一致性。这种方案适用于绝大多数需要前后端协同加密敏感信息的业务场景。以上就是 Go语言使用对称加密的详细内容,更多关于Golang AES加密的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。