如何在Golang中实现AES加密与解密 Go语言对称加密算法实战

2次阅读

aes密钥长度必须严格为16、24或32字节;ecb不安全,应使用cbc并确保iv随机且唯一;填充须用pkcs#7而非zero padding;解密失败需分层排查iv、密钥、填充及长度。

如何在Golang中实现AES加密与解密 Go语言对称加密算法实战

为什么 aes.NewCipher 总 panic: “invalid key size”?

go 的 AES 实现对密钥长度极其严格,只接受 16(AES-128)、24(AES-192)或 32(AES-256)字节的密钥,少一个字节或多一个字节都会直接 panic。常见错误是拿字符串字面量当密钥,比如 "mysecret"(8 字节)或 "this-is-a-32-char-long-key-123456"(33 字节)。

  • sha256.Sum256md5.Sum128 固定输出长度再截取:例如 sha256.Sum256([]byte("passphrase")).[0:32]
  • 别用 strings.Repeat 补位 —— 这不增加熵,还可能引入空字节导致解密失败
  • 如果从配置读密钥,务必检查 len([]byte(key)),不是 len(key)(后者对含中文或 emoji 的字符串会出错)

ECB 模式能用吗?为什么 cipher.NewCBCEncrypter 要自己传 IV?

不能用 ECB。它对相同明文块总生成相同密文块,像 "admin:true""user:false" 可能暴露结构,实际中基本等同于“没加密”。

CBC 是更安全的起点,但 IV 必须随机且每次加密不同:

  • IV 长度必须等于 AES 块大小(16 字节),和密钥长度无关
  • IV 不需要保密,但绝不能复用 —— 同一密钥下重复 IV 会让前两个块的异或关系可推测
  • 推荐把 IV 放在密文开头:先写 iv,再写加密后数据,解密时前 16 字节读作 IV
// 加密时 iv := make([]byte, aes.BlockSize) rand.Read(iv) // 注意 error 检查 block, _ := aes.NewCipher(key) mode := cipher.NewCBCEncrypter(block, iv) ciphertext := make([]byte, len(plaintext)) mode.CryptBlocks(ciphertext, plaintextPadded) result := append(iv, ciphertext...)

填充怎么处理?pkcs7zero padding 有什么区别?

Go 标准库不内置填充,必须手动补足到 16 字节整数倍。PKCS#7 是通用做法,而 zero padding 在明文末尾补 x00,但无法区分真实 x00 和填充位,解密时必然出错

立即学习go语言免费学习笔记(深入)”;

  • PKCS#7 填充规则:需补 n 字节,则填 n 个字节值为 n;若原文本刚好是 16 的倍数,则额外补 16 个 x10
  • 解密后必须验证最后一个字节值 ≤ 16,且末尾 n 字节全等于 n,否则报错(防篡改)
  • 别用 bytes.Repeat([]byte{0}, n) —— 这是 zero padding,不是 PKCS#7

解密失败时只返回乱码,怎么快速定位是哪步错了?

Go 的 AES 解密不会主动报错,错 IV、错密钥、错填充都会产出看似“成功”的乱码。排查要分层:

  • 先确认密文长度 ≥ 16(IV) + 16(至少一个密文块)
  • 检查解密用的 key 和加密是否完全一致(注意字符串编码、空格、换行)
  • 把 IV 单独提取出来,用 hex.EncodeToString(iv) 打印比对
  • 临时改用已知正确的测试密钥/IV(如全 0 的 [32]byte)跑通流程,再换回业务密钥

AES 本身简单,真正复杂的是密钥管理、IV 生成、填充验证、错误传播这四点。漏掉任意一个,都会让加密变成“看起来工作、其实裸奔”的状态。

text=ZqhQzanResources