浅聊一下前端加解密库 sm-crypto 踩过的坑

515 阅读2分钟

需求:是后端对视频文件加密,前端在播放的时候先进行解密才能播放。

背景:后端采用国密对视频进行加密,用ai搜了一下,决定用sm-crypto这个库(至于为什么用这个库,大家可以自己搜一下,这个不是本文重点)。因为是对视频加解密所以用的是 sm4 对称加密。

坑一、sm-crypto不支持ctr模式

开始后端用的是国密 ctr 模式对视频进行加密,看了sm-crypto的 npm 文档也没有说是否支持这种模式,直接一顿操作,解密成功,但是视频流无法播放,根本不知道什么原因。一顿搜索还是没找到问题原因,后来去看了下源码,直接上图,

image.png

发现只支持 cbc 与 ecb 两种模式,而且默认走的是 ecb 模式。 然后又是一顿搜索, 说 gm-crypto 库支持 ctr模式,于是换了个库操作了一波,结果还是不行。(这里各种 ai 回答都不一致, 有些说sm-crypto支持 ctr模式,有些说gm-crypto支持),结果是两种都不支持。附上gm-crypto的源码

image.png

结论: 只能让后端换一种加密模式,切换成了 cbc模式。

坑二、加密视频的数据格式

先说结论:后端对视频加密的数据是二进制数据流,而我采用的是将视频文件的二进制流转成 hex 数据, 因此不管怎么解密都是报错。 报错信息:解密失败: Invalid code point 1839170 (说到这个还要在吐槽一下, 我对解sm4.decrypt方法进行了 try catch, 发现好几种错误打印的都是这个错误码,压根没法区分)。这个问题导致了我没法解密后端加密的视频,后端也没法解密我加密的视频(因为我对加密的视频数据也行转了 hex 的转换), 但是我可以解密自己加密的视频,后端同样也可以。又是一顿搜索,还是没有结果。 最后打印了各种日志, 我发现我加密后的数据比加密前的大了一倍,然后去排查代码,发现多了hex数据转换这一步。 ps: 我是让 cursor 直接给我翻译了后端的加解密代码,生成的 js 代码。

以为这里就结束了,结果还有

坑三、解密后的二进制数据无法直接放在 video 标签播放

直接上结论:解密后的数据需要判断数据格式是否是Uint8Array类型, 如果不是就需要转换,上代码

image.png

终于成功了,当然在这个过程中还有一些别的小坑,没有全部记录。

前端菜鸟一枚,仅用于记录自己的日常开发, 大佬们轻喷~~~~~~