You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:57:10