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

使用OpenSSL加密AES-128 ClearKey HLS分片遇解密失败问题求助

AES-128 ClearKey加密MP4分片HLS失败排查

操作流程

  • 拿到生产环境生成的MP4格式HLS分片(无法控制分片生成过程)
  • 执行加密命令,试图用IV=0和密钥aaaaaaaaaaaaaaaa加密所有分片:
    find . -type f -name "*.mp4" -exec openssl aes-128-cbc -e -in {} -out {}.enc -p -nosalt -iv 00000000000000000000000000000000 -K 97979797979797979797979797979797 \; -exec mv {}.enc {} \;
    
  • 编辑.m3u8文件,添加密钥配置:
    #EXT-X-KEY:METHOD=AES-128,URI="https://www.myKeyServer.com/key.key",IV=0x00000000000000000000000000000000 
    
  • 在HLS测试播放器中验证效果

错误现象

  • 播放器1报错:
    Failed to find demuxer by probing fragment data, audio_und_2c_128k_aac_1.mp4
    
  • 播放器2报错:ERROR_DECRYPTING
  • 密钥服务器返回内容为明文字符串:
    aaaaaaaaaaaaaaaa
    

补充尝试

编写Python脚本批量加密分片,代码如下,但问题依旧:

import os
import subprocess

ENC_KEY = f"{ord('a')}"*16
print (ENC_KEY)

# Loop through all .mp4 files in the current directory
video_files = []
audio_files = []
for file in os.listdir():
        if not file.endswith(".mp4"):
                continue

        if "audio" in file:
                audio_files.append(file)

        if "video" in file:
                video_files.append(file)

video_files.sort()
audio_files.sort()

i = 0
iv = f"{i:032x}"

print ("video_files:", video_files)
print ("audio_files:", audio_files)

# Encrypt the init
def init_enc(files, iv):
    for f_name in files:
        if not "init" in f_name:
            continue
        orig = os.path.join("/app/tstEncription/output_files", f_name)
        enc = os.path.join("/app/tstEncription/output_files", f_name + "_enc")
        print (enc)
        subprocess.run(["openssl", "aes-128-cbc", "-e", "-in", orig,  "-out", enc, "-nosalt", "-iv", iv, "-K", ENC_KEY])

init_enc(video_files, iv)
init_enc(audio_files, iv)

def enc_files(files, _i):
    i = _i
    iv = f"{i:032x}"
    for f_name in files:
        if "init" in f_name:
            continue

        orig = os.path.join("/app/tstEncription/output_files", f_name)
        enc = os.path.join("/app/tstEncription/output_files", f_name + "_enc")
        print (enc)
        subprocess.run(["openssl", "aes-128-cbc", "-e", "-in", orig, "-out", enc, "-nosalt",  "-iv", iv, "-K", ENC_KEY])

        i = i + 1
        iv = f"{i:032x}"

enc_files(video_files, 1)
enc_files(audio_files, 1)

错误原因及修复方案

1. 密钥格式完全错误

加密时使用的是十六进制格式的密钥(9797...,对应16个ASCII字符a的十六进制值),但密钥服务器返回的是明文字符串aaaaaaaaaaaaaaaa,而HLS要求AES-128密钥必须是16字节的二进制原始数据,不是文本字符串。

修复:

  • 调整密钥服务器返回格式,直接返回16字节的二进制数据(即字节流b"aaaaaaaaaaaaaaaa"),而非文本。
  • 若用文件存储密钥,需用二进制模式写入:open("key.key", "wb").write(b"aaaaaaaaaaaaaaaa")。

2. 错误加密了整个MP4文件

HLS对MP4分片加密时,只能加密媒体数据(mdat box),必须保留moov、moof等容器元数据为明文。用OpenSSL直接加密整个MP4文件会把容器头也加密,导致播放器无法解析分片结构,出现“找不到解复用器”的错误。

修复:

  • 使用专门的MP4加密工具,比如MP4Box:
    MP4Box -crypt aes-128:key=97979797979797979797979797979797:iv=00000000000000000000000000000000 input.mp4 -output output.mp4
    
  • 或者用ffmpeg:
    ffmpeg -i input.mp4 -c copy -encryption_scheme cenc-aes-128 -encryption_key 97979797979797979797979797979797 -encryption_iv 00000000000000000000000000000000 output.mp4
    

3. IV使用不符合规范(可选但推荐)

虽然用同一个IV不会直接导致解密失败,但HLS规范推荐每个分片使用唯一IV,复用IV存在安全风险。若不同分片使用不同IV,必须在m3u8中为每个分片指定对应的IV(通过EXT-X-KEY的IV字段或EXT-X-MAP中的IV)。

4. 脚本密钥参数验证

脚本中ENC_KEY = f"{ord('a')}"*16生成的字符串9797...(32个字符)与命令行-K参数值一致,这部分是正确的,问题核心仍为密钥服务器返回格式和加密范围错误。

内容的提问来源于stack exchange,提问作者j.derek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 06:15:03