关于使用ClearKey配合Encrypted Media Extensions API加密文件的技术咨询
嘿,我正好折腾过ClearKey+EME的自定义加密实现,你的问题问到了很多人刚开始踩坑的点——核心逻辑你摸对了,但要让EME真的能认你的加密内容,确实不是单纯把字节数组加密就行,还有几个关键细节得跟上:
首先得给你吃颗定心丸:你对ClearKey的基础认知完全正确——它就是用对称加密算法(标准是AES-128-CBC)加密媒体段,再把同一份密钥传给客户端解密,是EME体系里最“无黑盒”的方案,没有第三方DRM的额外限制。但要让浏览器的EME API顺利处理,还差这几步:
不能直接加密整个文件/ArrayBuffer,得针对「媒体样本」下手
你没法把整个视频文件一股脑加密成乱码,EME要求的是加密媒体容器(比如MP4、WebM)里的单个媒体样本——也就是一帧视频或者一小段音频。比如MP4里mdat块里的每个独立样本,都要单独用AES-128-CBC加密,而且每个样本的IV(初始化向量)不能重复,通常是用样本序号生成的固定格式:比如MP4的IV一般是8字节的样本序号(大端字节序)加8字节的0,这样浏览器能自动解析对应。必须给媒体容器加「加密元数据标签」
浏览器得知道这个媒体是用什么加密的、对应哪个密钥ID,这些信息要嵌到媒体容器的特定位置里。比如MP4文件,你得在moov盒里加一个pssh(Protection System Specific Header)盒,里面要放ClearKey的专属系统ID(1077efec-c0b2-4d02-ace3-3c1e52e2fb4b),还有对应的密钥ID列表;同时还要在每个轨道的stsd盒里加加密描述子,指定加密算法、IV长度这些参数。WebM的话,要在Segment Info里加对应的加密元素。没有这些元数据,浏览器根本识别不出这是个加密媒体,EME直接就罢工了。密钥得按EME要求的格式传
你传给EME的密钥不能是原始的16字节二进制,得包装成JWK(JSON Web Key)格式。举个例子:把16字节的密钥转成base64url编码,放到JWK的k字段里,同时指定alg: "A128KW"、kty: "oct",而且kid(密钥ID)必须和你嵌在媒体容器里的pssh盒里的密钥ID完全对应,不然EME会找不到匹配的密钥。
如果你想纯代码实现(不用ffmpeg这类工具),完全可行,但得自己手动处理媒体容器的解析和修改流程:
- 先解析MP4/WebM的容器结构,把所有媒体样本提取出来;
- 用AES-128-CBC加密每个样本,用正确的IV;
- 往容器里添加
pssh盒和加密描述子; - 把加密后的样本和修改后的容器重新组装成完整文件。
建议你可以先拿一个极小的测试MP4文件练手,先搞定pssh盒的添加,再逐步处理样本加密,这样调试起来更容易定位问题。
内容来源于stack exchange

