去年冬天,一个做录播系统的朋友抱着设备找过来,说新采购的 4K 采集卡接老款投影,画面每隔十几秒就黑一下,黑了又自己恢复,主机日志干干净净什么都不报。我先怀疑线材,换了三根,换了两个口,现象照旧;又怀疑分辨率协商,把输出锁到 1080p60,还是黑。最后把 DDC 上的 I2C 报文抓出来,才看到HDCP1.4的链路完整性校验每隔一段时间就对不上一次,发送端直接掐断信号重新握手。这类问题在我这几年经手的显示链路里占比不低,而且第一次遇到的人基本不知道该往哪个方向查,因为现象看起来像线材、像兼容性、像驱动,唯独不像"内容保护协议在打架"。HDCP1.4 就是跑在 HDMI 链路 DDC 通道上的一套内容保护协议,管的是"这段视频能不能被这台显示设备解密播放",它决定了你的信号源、分配器、采集卡、投影之间能不能顺利握手,也决定了出问题时你该从哪里下手。接下来我把这套协议的骨架、密钥推导、加密器和实际调试中踩过的坑,按从业者的视角完整拆一遍,从刚接触 HDMI 调试的新手到需要自己实现协议栈的固件工程师,都能从中找到可以直接抄的部分。
1. 先搞清楚 HDCP1.4 在链路里扮演什么角色
1.1 一条 HDMI 线里同时跑的三种数据
很多人把 HDMI 当成"一根传视频的线",实际上它内部至少并行跑着三套东西,理解这三套东西的分工,是理解 HDCP1.4 的前提。第一套是主数据通道,也就是 TMDS(老版本)或 FRL(新版本)链路,跑的是视频像素、音频采样和各类控制包,带宽最大;第二套是 DDC 通道,本质就是一条 I2C 总线,跑 EDID 读取和 HDCP 认证所需的全部消息交互;第三套是 CEC 和 HPD 这类低速控制线,负责设备发现和热插拔通知。HDCP 的巧妙之处在于,它把"谈判"放在带宽极低的 DDC 上,把"干活"放在主数据通道上——先通过 I2C 完成密钥协商,协商成功后才打开主通道上的加密器。
这个分工带来一个非常实际的后果:认证阶段出问题,表现往往是整条链路不通或者黑屏;加密阶段出问题,表现是画面间歇性中断、闪黑、雪花或者采集卡录出来的文件花屏。这两类故障的排查路径完全不同,前者要去看 I2C 报文,后者要去查帧同步和密钥流。我在实际项目里见过太多人把后者当前者查,折腾半天换线换口,其实问题在加密器复位时机上。
还有一个容易误解的点:HDCP1.x 加密的只有视频像素数据,音频采样、InfoFrame、控制包都是明文传输的。这不是设计缺陷,而是当年的权衡——音频数据量小、敏感度低,加密它带来的复杂度和延迟收益不划算。所以你在抓取链路数据时看到音频正常但画面花屏,完全不要怀疑是音频通道出了问题。
1.2 1.4 版本相对早期版本到底改了什么
网上一搜 HDCP 版本,能看到 1.0、1.1、1.2、1.3、1.4 一大串,还有 2.0、2.1、2.2、2.3,很容易看晕。按公开资料和实际设备行为整理,1.x 系列的演进大致是这样一条线:1.0 是初版,定义了最基础的认证握手和加密器;1.1 之后陆续补充了对中继设备(Repeater)的支持、密钥撤销列表的传递机制;1.3 主要是完善了合规测试要求;1.4 则是对着 HDMI 1.4 引入的新特性做适配,把中继器的行为、下游设备数量上限、拓扑上报这些细节做了明确化。
我个人的理解是,1.3 和 1.4 在互操作层面几乎没有实质差异。做过实测的同行应该有同感:一台标称 1.3 的显示设备和一台标称 1.4 的信号源,握手流程、消息长度、密钥推导方式完全一致,正常配合毫无问题。真正会因为版本不同而出现差异的,是那些"半吊子实现"——比如某些低成本分配器只实现了 1.3 的子集,遇到 1.4 信号源发来的拓扑请求就直接超时;再比如某些老投影的固件里,1.4 才明确要求处理的某个状态位没有实现,导致中继场景下反复重认证。
所以你在选型和排查时,不要把"支持 1.4"当成一个硬性卖点去比对,它更像是一个"补丁版本"。真正需要关注的是设备有没有完整实现中继器逻辑、KSV 列表能不能正确上报、以及密钥撤销列表支不支持更新。这三点才是实际使用中会咬人的地方。
| 版本 | 主要变化 | 实际影响 |
|---|---|---|
| 1.0 | 基础握手与加密器定义 | 单跳直连场景可用 |
| 1.1 | 补充中继器支持 | 分配器、功放串联场景开始可用 |
| 1.2 | 密钥撤销机制细化 | 支持通过固件更新吊销泄露的设备密钥 |
| 1.3 | 合规测试要求完善 | 通过认证的设备互操作性更好 |
| 1.4 | 适配 HDMI 1.4,明确拓扑与下游数量 | 多级串联、复杂拓扑场景行为更可预期 |
1.3 三个角色和它们的职责边界
HDCP1.4 的世界里只有三种角色,但这个划分必须刻在脑子里,否则看规范会一直绕不出来。发送端(Transmitter)是信号源,比如机顶盒、电脑显卡、手机投屏器,它持有自己的 Aksv(40 位密钥选择向量)和与之配套的私钥,负责发起认证、生成会话密钥、驱动加密器。接收端(Receiver)是显示设备,持有自己的 Bksv 和配套私钥,负责响应认证、解密、上报状态。中继器(Repeater)是介于两者之间的设备,比如功放、分配器、切换器,它对上游表现为接收端,对下游表现为发送端,需要在两个方向上分别完成认证,还要把下游的设备列表汇总上报。
这个"双面人"设定是很多问题的根源。中继器内部要维护一张 KSV 列表,记录所有下游设备的 40 位标识,上限是 127 个;要把自己的拓扑深度、设备数量通过状态寄存器报给上游;还要处理"下游设备热插拔导致列表变化"这种动态事件。我在一个多屏拼接项目里就吃过亏:现场用了三级分配器串接,最末端插拔任意一台显示器,整条链路都会黑屏两三秒重新握手。当时以为是分配器质量差,后来把拓扑信息读出来才发现,中间那级分配器每次下游变化都把自己整个重置了一遍,而不是只更新 KSV 列表,上游自然被迫重新认证。
角色划分还有一个隐含约束:发送端和接收端之间是点对点的,一对多必须经过中继器。你不能把一个信号源直接并联到两台显示器上,那样两条 DDC 会打架。市面上那些"一进二出"的廉价分线器,本质上就是一个没有完整实现中继器逻辑的中继器,所以才会出现两台显示器只有一台能亮、或者两台都亮但其中一台间歇闪的情况。
2. 认证握手的三段式结构拆解
2.1 第一步 AKE_Init:证书、随机数和触发
整个认证流程的第一阶段叫 AKE(Authentication and Key Exchange),可以理解成"双方先亮身份证、再对暗号"。发送端先通过 DDC 读走接收端的 Bksv,这是一个 40 位的设备标识,相当于身份证号;同时把自己的 Aksv 写进接收端。这两个值都不是秘密,它们在链路上明文传输,作用只是让对方知道"我在跟谁说话"。
接着发送端生成一个 64 位的随机数 An,写进接收端,然后触发 AKE_Init。这个 An 非常关键,它有两个用途:一是作为后续加密器的初始种子之一,二是参与会话密钥的推导,保证每次上电握手产生的密钥流都不一样。我在实现协议栈的时候踩过一个坑——为了省事把 An 写死成固定值,功能测试全过,但一上产线做兼容性测试,某几款老显示器就开始随机黑屏。原因很简单,某些接收端实现里对重复的 An 做了缓存判断,看到一模一样的值就认为是重放攻击,直接拒绝。An 必须是真随机或者高质量伪随机,每次握手都要变。
触发动作本身也有讲究。规范里是通过向特定消息偏移写入一个触发字节来启动流程,但不同芯片厂商的封装层会把它映射成完全不同的寄存器操作,有的甚至封装成一条命令队列。我见过一个方案,触发写完必须等至少 5 毫秒才能读状态,早一毫秒读到的都是上一次的残留值。这种时序细节规范里不会写,只能靠示波器或者反复实测摸出来。
注意:Aksv 和 Bksv 是明文传输的,不要把它们当成密钥。它们是标识,不是秘密。真正的秘密是设备内置的私钥和推导出来的会话密钥。
2.2 第二步 解密 Km' 与推导会话密钥
发送端在这一步生成一个 56 位的随机数 Km,这是整个会话的种子。它用自己持有的一把私钥对 Km 做 RSA 运算,得到一个 64 字节的密文 Km',写进接收端。接收端收到之后,用自己的私钥解密,还原出 Km。这一步是整个协议里唯一用到非对称加密的地方,也是开销最大的一步——1024 位的 RSA 运算,在低成本 MCU 上跑一次可能要几十毫秒。
这里有一个初次接触时最容易困惑的点:为什么接收端能解开发送端加密的东西?答案藏在规范的密钥分配体系里——每台设备出厂时都被烧录了一组密钥材料,发送端和接收端各自持有配套的私钥,这对密钥在分配时就是成对的。实际工程中你根本不需要自己实现 RSA,芯片里都有硬件加速引擎,你只要把 Km' 丢进去、等中断、取结果就行。真正需要自己写的部分是密钥推导。
解密出来的结果并不是直接可用的 Km。规范里对这段数据结构有明确的位域定义:解密输出里有一段是填充,真正的 Km 只有 56 位,藏在特定位置。我第一次实现的时候把端序搞反了,握手永远停在这一步,接收端算出来的 R0' 和发送端算出来的 R0 对不上,查了整整两天,最后把双方中间值打印出来逐字节比对才发现问题。这种位域定义必须照着规范原文的图来,不要凭直觉拼。
拿到 Km 之后,双方各自计算会话密钥 KS。计算方式是拿 Km 和上一轮的 R0 做异或,取高 40 位;首次认证时 R0 视为全零,所以第一次的 KS 就是 Km 的高 40 位。接着用 KS 加一段零填充做 SHA-1,取其中 40 位得到 KS1;再把 KS1、Km、Ki 按规范定义的位域拼成一个 160 位的中间密钥 Kd,供后面的 HMAC 使用。这一串推导看着繁琐,其实每一步都有明确目的:KS 用于加密器播种,KS1 用于防止密钥直接暴露,Kd 用于完整性校验的 HMAC。
2.3 第三步 R0 校验:为什么双方要各算一遍
密钥推导完成后,发送端和接收端各自用相同的方式计算 R0:把 KS、一个固定的 64 位常量 M0、以及一个随机量拼在一起做 SHA-1,得到 20 字节的结果。发送端算完自己的 R0,再去读接收端算出来的 R0',两者比对,相等才算认证通过。
这个设计看起来有点多余——密钥都一样了,还比对什么?实际上这是整套协议里最精妙的一环。RSA 解密、位域提取、密钥推导,每一步都可能因为实现差异产生不同的结果,而 R0 是一个 160 位的哈希,任何一位不同都会导致结果面目全非。它相当于一次端到端的自检:只要双方算出的 R0 一致,就证明从 Km 到 KS 到 Kd 的整条推导链路完全对齐。这比逐字段校验高效得多,也隐蔽得多。
M0 是一个固定的常量,规范附录里给了具体数值。我要提醒的是,这个值在不同版本的规范文档里排版可能有差异,直接复制粘贴容易带进不可见字符。我就见过一个团队因为复制时多带了一个空格,导致 SHA-1 输入长度不对,R0 永远对不上,最后是用十六进制编辑器逐字节比对才发现的。
校验失败的处理也值得说。规范要求发送端在 R0 不匹配时不能继续,必须重新走一遍 AKE。但实际设备的行为五花八门:有的会重试三次然后放弃并报错,有的会无限重试导致画面一直闪,还有的会"假装成功"继续输出但在加密器上做手脚,结果就是画面花屏。如果你在做兼容性测试,遇到"握手报成功但画面异常"的情况,优先怀疑这一类。
2.4 第二阶段 Repeat Authentication:轻量化的二次握手
AKE 完成之后,链路进入正常传输状态,但认证并没有结束。HDCP1.4 还有一个叫 Repeat Authentication 的第二阶段,它的目的不是重新协商密钥,而是确认"对面还是刚才那个设备,链路没被中途换掉"。
这个阶段的流程轻得多:发送端生成一个 64 位的随机数 rtx,用 Kd 做 HMAC-SHA1 得到一个 16 位的 Ri,发给接收端;接收端用同样的方式算出 Ri' 回传;发送端比对,一致就继续。整个过程只有两次消息往返,开销极小,可以频繁执行。
为什么需要这个阶段?设想一个攻击场景:有人在中途拔掉显示器,换上一台录像设备,如果只有 AKE,录像设备拿不到密钥就没法解密,但它可以假装成原显示器继续接收加密流,虽然解不开内容,却能完整录下密文。Repeat Authentication 通过定期的随机挑战,让"冒充者"必须能算出正确的 Ri',而算 Ri' 需要 Kd,Kd 又需要 Km,Km 只有真正的接收端才解得开。这就把"换设备"这条路堵死了。
实际实现中,rtx 的生成频率和随机性也要注意。有些低成本方案为了省事,rtx 用的是递增计数器而不是随机数,短期看不出问题,长期跑下来会被某些严格的接收端判定为异常。规范里明确要求 rtx 是随机值,别偷这个懒。
3. 密钥体系与加密算法细节
3.1 五组密钥的关系梳理
HDCP1.4 里出现的密钥名目不少,初次接触很容易混。我把它们按"生命周期"和"作用范围"两个维度理一遍,实际写代码时对着这张表查,比翻规范快得多。
| 名称 | 长度 | 来源 | 生命周期 | 用途 |
|---|---|---|---|---|
| Aksv | 40 位 | 发送端出厂烧录 | 永久 | 发送端身份标识,明文传输 |
| Bksv | 40 位 | 接收端出厂烧录 | 永久 | 接收端身份标识,明文传输 |
| Km | 56 位 | 发送端每次握手随机生成 | 单次会话 | 会话种子 |
| Km' | 64 字节 | Km 经 RSA 运算得到 | 单次会话 | 传输形态的 Km |
| KS | 40 位 | Km 与 R0 异或取高位 | 单次会话 | 加密器播种 |
| KS1 | 40 位 | KS 经 SHA-1 派生 | 单次会话 | 中间密钥材料 |
| Kd | 160 位 | KS1、Km、Ki 拼接 | 单次会话 | HMAC 密钥 |
| Ki | 40 位 | 设备内置 | 永久 | 密钥材料之一 |
看懂这张表的关键是分清"永久"和"单次会话"。Aksv、Bksv、Ki 是烧在芯片里的,出厂就定了,改不了;Km 及其派生的一切都是每次握手重新生成的,断了重连就全换。这个区分在排查问题时特别有用:如果故障在每次重连后都复现,那大概率是永久密钥或者推导逻辑的问题;如果故障是偶发的、跟时间相关,那更可能是随机数质量或者时序问题。
还有一个容易被忽略的细节:Ki 这个名字在不同资料里可能指代不同的东西,有的文档把设备内置的密钥矩阵叫 Ki,有的把某个中间量叫 Ki。看资料时一定要确认上下文,别把两个不同的东西当成同一个。
3.2 SHA-1 与 HMAC-SHA1 的三处用途
这套协议里用到了三处哈希运算,用途各不相同,实现时最好分开写三个函数,别图省事复用一个。
第一处是 R0 的计算,用普通 SHA-1,输入是 KS、M0 和随机量拼接,输出 20 字节,用于端到端自检。第二处是 KS1 的派生,也是普通 SHA-1,输入是 KS 加零填充,输出取其中 40 位。第三处是 Ri 的计算,用 HMAC-SHA1,密钥是 Kd,消息是 rtx,输出取 16 位用于链路校验。
这里要特别说明一个实际工程中的坑:SHA-1 的填充规则必须严格遵守。SHA-1 在计算前会对消息做填充,补一个 1、若干 0、再补 64 位长度。有些轻量级实现为了省代码,直接对固定长度输入做简化处理,在输入长度恰好是 56 字节的整数倍时就会算错。HDCP 的消息长度是固定的,正常情况下不会触发这个边界,但如果你在调试时手动构造了变长输入去验证,就会撞上。
另外,SHA-1 在现代密码学语境下已经不被认为是安全的哈希算法,但在 HDCP1.4 这个语境里,它的作用是"快速比对"而不是"抗攻击",所以规范沿用它是有历史原因的。你不需要也不应该去替换它——替换了就不兼容了。
3.3 56 位 LFSR 流加密器的工作方式
真正的加密动作发生在像素数据上,用的是流加密:一个 56 位的线性反馈移位寄存器(LFSR),每来一个时钟输出一位,攒够 24 位就得到一个像素的密钥流,和像素值异或。解密端用完全相同的结构和相同的种子,就能还原出原始像素。
LFSR 的结构在规范里有明确的抽头定义,哪几位参与反馈、反馈到哪一位,都是固定的。实现时最容易出错的地方是初始化:LFSR 的初值不是直接用 KS,而是要经过一次特定的装载过程;每帧开头还要用会话密钥重新播种,保证帧与帧之间的密钥流不重复。我见过一个方案为了省资源,只在链路建立时播种一次,之后一直跑,结果跑几小时后画面开始出现规律性噪点——原因是 LFSR 的周期有限,长时间不重置会进入循环。
还有一个位深的问题。1.4 支持 8 位、10 位、12 位色深,不同位深下加密器的处理方式不同:低位深时每个像素 24 位直接异或,高位深时需要按规范定义的方式拆分处理。很多低成本方案只实现了 8 位路径,接 10 位色深的信号源就出问题,表现是色彩断层或者局部花屏。如果你的设备要支持 HDR 和高色深,这一块必须完整实现,不能只做 8 位兼容糊弄过去。
3.4 几个流传很广的误传
第一个误传是"HDCP 会降低画质"。这个说法在早期有一定的现实基础——某些劣质分配器为了降低加密器实现难度,会把输入信号强制降到 8 位色深再加密输出,用户看到的就是色彩变差。但这不是协议本身的问题,是设备实现偷工减料。正规实现的 HDCP1.4 是无损的,加密前后像素值完全一致。
第二个误传是"HDCP 加密会导致延迟"。加密器本身是纯组合逻辑加一个移位寄存器,延迟在纳秒级,可以忽略。用户感知到的延迟来自别处——比如某些设备在检测到 HDCP 握手时会重新协商分辨率,那一下黑屏确实有几百毫秒,但那是重新协商的代价,不是加密的代价。
第三个误传是"HDCP 坏了可以刷固件修好"。密钥是烧在一次性存储里的,刷固件改不了。如果设备的 KSV 被列入撤销列表,唯一的出路是换芯片或者换整机。这一点在做长周期项目选型时特别重要——选那些密钥管理规范、有正规认证的器件,别为了省几毛钱选来路不明的方案,后面被撤销了整批货都得召回。
4. 链路完整性校验与拓扑管理
4.1 128 帧一次的 Ri 对账机制
链路建立之后,发送端并不会一直闷头加密,它要定期确认对面还在、密钥还对。这个确认动作就是 Ri 对账,规范建议的频率是每 128 帧一次——按 60 帧每秒算,大约两秒一次。
具体流程是这样的:发送端在某个时刻生成 rtx,用它和 Kd 算出 Ri,通过 DDC 写给接收端;接收端收到后,用自己的 Kd 算 Ri',写回自己的状态寄存器;发送端在下一个检查点读回 Ri',和自己算的比对。一致就继续,不一致就触发重认证。
这个机制的实现有几个细节值得注意。第一,Ri 的读写必须在帧消隐期完成,因为 DDC 是低速总线,传输过程中如果占用主通道会影响画面。第二,比对窗口要留足余量,有些接收端响应慢,你发出去立刻读会读到旧值。第三,连续多次失配才重认证,偶发一次可能是总线干扰,直接重认证会导致画面频繁闪断,体验极差。我在实际项目里用的是"连续三次失配才重认证"的策略,稳定性明显好于规范的最低要求。
4.2 失配之后的处理路径
一旦确认 Ri 对不上,发送端要做的事情按顺序是:先停止输出加密视频(或者输出全黑),然后清空当前会话密钥,重新走一遍完整的 AKE 流程。整个过程中接收端会经历一次 HPD 或者内部复位,用户看到的就是黑屏一到三秒。
这里有一个优化空间。规范允许发送端在重认证期间保持视频时序不变,只把像素数据替换成固定值(比如全黑或测试图案),这样显示器不会重新协商分辨率,恢复速度快很多。很多做得好的设备就是这么处理的,用户感知到的只是"闪了一下"而不是"黑屏重连"。我在一个机顶盒项目里把这块优化过,重认证的恢复时间从 2.8 秒压到 0.4 秒,客诉率直接降了一个数量级。
反之,如果接收端在重认证期间丢失了信号,重新检测 HPD,那就要重新读 EDID、重新协商分辨率,整个过程可能五秒以上。这就是为什么有些设备"闪一下就好",有些设备"黑屏半天"——差别不在协议,在处理策略。
4.3 中继器、KSV 列表与下游数量限制
中继器的核心职责是维护一张下游设备列表。每当有新的下游设备接入,它要把对方的 KSV 加进列表;设备拔出,从列表里删掉;列表变化要通知上游,上游再决定是否重新认证。规范规定这个列表最多 127 项,拓扑深度最多 7 级。
这两个数字在实际工程中的意义比看起来大。127 项意味着你最多能串 127 台设备,超过这个数就没法完整上报了;深度 7 级意味着串接层数有限,但实际项目中三层串接就已经很罕见了。真正麻烦的是"列表变化引发连锁重认证"这个问题。
设想一个会议室场景:一台主机接一台功放,功放接一台投影,投影旁边还有一个备用显示器通过分配器挂着。有人给备用显示器插上电源,分配器的 KSV 列表变化,通知功放,功放通知主机,主机重新认证,整条链路黑一次。虽然备用显示器根本没在播放,但它的接入影响了主链路。这个问题在所有不支持"部分重认证"的设备上都存在,解决办法只有一个——尽量用星型拓扑,别串太多级;下游设备不用的时候物理断开,别让它挂在那儿。
5. 工程落地实操:从寄存器配置到日志分析
5.1 硬件与软件的分工边界
做 HDCP1.4 相关开发,首先要搞清楚哪些活是芯片干的、哪些活是你干的。RSA 运算、SHA-1 计算、加密器这些,现代 SoC 基本都有硬件加速,你要做的是配置、触发、读结果;密钥推导、状态机管理、异常处理、和中继器的列表维护,这些必须软件实现。
我建议在动手写代码之前,先把芯片手册里 HDCP 相关的寄存器列表抄一遍,标注清楚哪些是只读状态、哪些是写入触发、哪些需要轮询。这一步花两小时,能省后面两天。我见过太多人跳过这一步直接写代码,结果在"写完触发位之后要不要清"这种问题上卡住。
还有一个现实问题:不同厂商的寄存器映射差异极大。同样一个"读 Bksv"的操作,A 厂可能是读 0x00 开始的 5 个字节,B 厂可能封装成一条命令发出去、从 FIFO 里读回来。所以代码里最好加一层抽象,把"读 Bksv""写 An""触发 AKE"这些动作封装成函数,换平台时只改底层。
5.2 抓包时该看哪三个观察点
调试 HDCP 问题,抓 DDC 上的 I2C 报文是最有效的手段。但抓下来一堆数据怎么看?我一般看三个点。
第一个点是握手的完整性和顺序。正常的 AKE 应该能看到:读 Bksv → 写 Aksv → 写 An → 写 Km' → 触发 → 读状态 → 读 R0'。如果中间少了某一步,或者顺序错了,说明状态机有问题。我遇到过一次,发送端在写完 Km' 之后没等接收端准备好就触发了,导致接收端根本没处理,握手当然失败。
第二个点是时间间隔。每一步之间的间隔应该在一个合理范围内,太快说明没等对方准备好,太慢说明有阻塞。我用逻辑分析仪看过一个案例,某设备的 AKE 流程中间有 300 毫秒的空档,查下来是软件在两次 I2C 操作之间做了一次不必要的大延时,把整体握手时间从 80 毫秒拖到了 400 毫秒。
第三个点是重试次数。如果看到同一条消息反复出现,说明在重试。重试本身不一定是坏事,但频繁重试就要查原因了——可能是总线拉不起来,可能是对方没响应,也可能是时序没对齐。
5.3 一个最小可验证的实现顺序
如果你要从零实现一套协议栈,我建议按这个顺序推进,每一步都能独立验证,出问题好定位。
第一步,只做 DDC 读写,能正确读出 Bksv、正确写入 Aksv,然后读回来确认。这一步验证的是 I2C 时序和寄存器映射。第二步,加 RSA 运算,自己加密、自己解密,验证 Km' 的位域处理是否正确。第三步,实现密钥推导,把中间值全部打印出来,和参考实现逐字节比对。第四步,实现 R0 计算和比对,跑通