如何用Golang解密AES加密TS传输流段?遇IV长度问题求解
解决
cipher.NewCBCDecrypter: IV length must equal block size 错误 咱们先从触发panic的核心问题说起:AES算法的块大小是固定的16字节(128位),而CBC加密模式要求IV(初始向量)的长度必须和块大小完全一致。你提供的IV十六进制字符串353833383634解码后只有6字节,远达不到16字节的要求,所以直接触发了这个错误。
为啥OpenSSL命令能正常跑?
OpenSSL的aes-128-cbc命令做了“兜底”——当你指定的IV长度不足块大小时,它会自动用0字节填充到16字节。所以在Go代码里,我们需要手动复刻这个行为。
修正IV的处理
把解码后的IV切片补0到16字节就行:
iv, err := hex.DecodeString("353833383634") checkerror(err) // 补0到AES块大小(16字节) if len(iv) < aes.BlockSize { iv = append(iv, make([]byte, aes.BlockSize - len(iv))...) }
还有这些坑要注意
解决IV问题后,你的代码和OpenSSL命令的行为还有几个不一致的地方,得修正才能得到相同的解密结果:
1. 处理PKCS#7填充
OpenSSL的aes命令默认用PKCS#7填充(除非你加-nopad参数),但Go的crypto/cipher包的CryptBlocks只会老老实实处理整数倍块大小的数据,不会自动处理填充。所以解密完成后,咱们得手动去掉PKCS#7填充:
// 去除PKCS#7填充:最后一个字节的值就是填充的长度 padding := ciphertext[len(ciphertext)-1] ciphertext = ciphertext[:len(ciphertext)-int(padding)]
2. 别再打印二进制数据啦
你的代码目前是把解密后的内容直接打印到控制台,这不仅会出现一堆乱码,还没保存成文件。咱们得像OpenSSL那样把结果写入clear.ts:
// 用os.WriteFile替代ioutil(ioutil在Go1.16+已被废弃) err = os.WriteFile("clear.ts", ciphertext, 0644) checkerror(err)
3. 大文件的优化(可选)
如果你的enc.ts是个大文件,一次性读进内存会占很多资源。可以改成分块读取、解密、写入的方式,避免内存溢出——不过小文件的话,一次性处理完全没问题。
完整的修正代码
package main import ( "crypto/aes" "crypto/cipher" "encoding/hex" "fmt" "os" ) func checkerror(err error) { if err != nil { panic(err) } } func main() { key, err := hex.DecodeString("9e8c69bcaafa6b636e076935e29986b5") checkerror(err) iv, err := hex.DecodeString("353833383634") checkerror(err) // 补0让IV长度等于AES块大小 if len(iv) < aes.BlockSize { iv = append(iv, make([]byte, aes.BlockSize-len(iv))...) } // 读取加密文件 ciphertext, err := os.ReadFile("enc.ts") checkerror(err) block, err := aes.NewCipher(key) checkerror(err) // 初始化CBC解密器 mode := cipher.NewCBCDecrypter(block, iv) // 解密:CryptBlocks会直接修改输入切片,节省内存 mode.CryptBlocks(ciphertext, ciphertext) // 去除PKCS#7填充 padding := ciphertext[len(ciphertext)-1] ciphertext = ciphertext[:len(ciphertext)-int(padding)] // 写入解密后的文件 err = os.WriteFile("clear.ts", ciphertext, 0644) checkerror(err) fmt.Println("解密完成!已经生成可播放的clear.ts文件啦") }
验证结果
运行完代码后,直接用ffplay clear.ts测试,应该和OpenSSL命令生成的文件效果完全一样。
内容的提问来源于stack exchange,提问作者hendry
相关产品推荐
相关产品推荐

