大家好,欢迎来到IT知识分享网。
hdcp简介
hdcp算法介绍
1.密码学算法
本文简单介绍hdcp涉及的加密算法流程,主要是dh和sha-1,后续可能会补充下des,rsa,hmac,伪随机数发生器,lfsr等内容。
1.1.Diffie-Hellman密钥交换算法
{}表示集合,这个公式很好理解,一个数mod一个素数p,其值一定不为0,只可能是1 和 p-1之间的数。
有 ,证明如下:
两者计算得到的一定相等,后面我们可以看到,hdcp第一阶段的交换过程的原理与之类似。
1.2 sha-1算法介绍及其c代码实现
sha-1,全称Secure Hash Algorithm,sha-1生成160bit的数据,sha-256生成256bit的数据,相比与sha256而言,sha-1安全性是比不上的,但是sha-1和sha-256大致流程类似,sha-1更容易理解其流程,更容易实现。
sha-1,输入为长度为0-2^64bit的消息,输出160bit的消息摘要,大致流程如下:
将消息m分组,每组512bit,最后一组不够512bit,在最后一组补1,其余位补0,直到满足最后一组的L mod 512 = 448;512 – 448 = 64,64为预留的消息的长度。
接着一组一组的进行处理,将每组的512bit分成16 * 32,也就是16份,每份32bit,进行预处理,按下图所示的方式处理成80组,
接着初始化5个常量,用于计算
将上面初始化的常量赋值给abced,再按如下图所示的方式进行80轮迭代
sha-1的代码如下:
#include<stdio.h> /*定义用到的常量*/ unsigned int A = 0x, B = 0xEFCDAB89, C = 0x98BADCFE, D = 0x, E = 0xC3D2E1F0; //第一次迭代的链接变量 unsigned int K[4] = { 0x5A, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6}; //循环中用到的常量 unsigned int A0 = 0x,B0 = 0xEFCDAB89,C0 = 0x98BADCFE,D0 = 0x,E0 = 0xC3D2E1F0; /*字节转字*/ int CharToWord(unsigned char *character, int first) { int temp = (((int)character[first] & 0x000000ff) << 24) | (((int)character[first + 1] & 0x000000ff) << 16) | (((int)character[first + 2] & 0x000000ff) << 8) | ((int)character[first + 3] & 0x000000ff); return temp; } /*f函数*/ unsigned int f(int B, int C, int D, int t) { return (t >= 0 && t <= 19) ? ((B&C) | (~B&D)) : ((t >= 20 && t <= 39) ? (B ^ C ^ D) : ((t >= 40 && t <= 59) ? ((B&C) | (B&D) | (C&D)) : ((t >= 60 && t <= 79) ? B ^ C ^ D : 0))); } /*从W消息分组中导出*/ void GetExtraMessage(unsigned int w[]) { for (int i = 16; i < 80; i++) w[i] = ((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]) << 1) | ((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]) >> 31); } /*分组*/ void DevideToGroup(unsigned char *plaintext,unsigned int *group,int length) { //512 - 64 = 448; //448 - (length + 1) 0的个数 //填充 unsigned char temp[64] = {0}; for (int i = 0; i < length; i++) temp[i] = plaintext[i]; temp[length] = 0x80; int len = length * 8; for (int i = 0; i <= 7 && len; i++) { temp[63 - i] = len & 0xff; len = (len >> 8); } for (int i = 0; i < 16; i++) group[i] = CharToWord(temp, i * 4); } unsigned int GetK(int t) { return (t >= 0 && t <= 19) ? K[0] : ((t >= 20 && t <= 39) ? K[1] : ((t >= 40 && t <= 59) ? K[2] : ((t >= 60 && t <= 79) ? K[3] : 0))); } /*步函数*/ unsigned int StepFunction(unsigned int w[],int t) { unsigned int temp = ((A << 5)|(A >> 27)) + f(B, C, D, t) + E + w[t] + GetK(t); E = D,D = C,C = ((B << 30) | (B >> 2)),B = A,A = temp; printf("第%2d轮加密后的密文是%08X %08X %08X %08X %08X\n", t + 1, A, B, C, D, E); } /*密文组合*/ unsigned int CombineCipher(unsigned int cipher[]) { for (int i = 0; i <= 4; i == 0 ? cipher[i] = (A0 + A) : (i == 1 ? cipher[i] = (B0 + B) : (i == 2 ? cipher[i] = (C0 + C) : (i == 3 ? cipher[i] = (D0 + D) : (i == 4 ? cipher[i] = (E0 + E) : 0)))), i++); } int main() { int i, t, j, length, temp; unsigned char plaintext[64] = "abc", hash[20] = { 0 }; unsigned int group[80] = { 0 }, cipher[5] = { 0 }; /*长度填充到最后*/ printf("当前明文字符串为:"); for (i = 0; plaintext[i]; length = i + 1,i++) { printf("%c", plaintext[i]); group[15] = (i + 1) * 8; //长度是二进制位数 } /*分组填补*/ printf("\n\n0x00 正在分组…………\n"); DevideToGroup(plaintext, group, length); /*从w消息分组中导出*/ GetExtraMessage(group); /*80次步函数*/ printf("\n0x01 SHA-1加密中…………\n\n"); for (t = 0; t < 80; t++) { StepFunction(group, t); if (!((t + 1) % 20)) printf("\n"); } /*密文组合*/ printf("\n0x02 hash值组合中…………\n\n"); CombineCipher(cipher); /*密文输出*/ printf("\n0x03 SHA-1加密成功!!!\n\nHash:"); for (j = 0; j <= 4; j++) printf("%08X", cipher[j]); printf("\n"); return 0; }
运行结果如下:
文献给的算例结果如下:
可以看到,编写的c代码算出的结果与sha文献中给出的结果一致,验证了代码的正确性。
2.hdcp协议流程&代码注解与分析
hdcp流程参考上海交大的论文基于 HDMI 的 HDCP 认证及加密的软件实现以及hdcp1.4的spec来进行讲解,介绍hdcp1.4的流程与实现,hdcp1.4一般是用硬件来实现的,软件做的话会比较慢。交大的这篇论文最后的实验结果是跑在intel core i5双核超线程2.8G处理器上,用优化后的软件版本,软件在1920×1080的高清分辨率下,达不到60帧。说明软件实现速度是不够了,距离这篇论文过去十几年,电脑以及芯片性能肯定有提升,但跑在芯片上,最多只能支持hdmi1.4,hdmi2.0的4k60用软件去跑负载肯定会非常重,更不用提hdmi2.1了。
2.1 hdcp1.4流程
2.1.1 hdcp1.4第一阶段
HDCP
发送器设备
A
可以随时发起认证,即使 之前已经有一次认证已经结束。认证的发起从 HDCP
发送器发送一个初始消息开始,这 个初始的认证消息包括设备A
的密钥选择向量
AKSV
和一个
64bit
的随机数。这个
64bit 的随机数是由 hdcp
的函
hdcpRngCipher
来产生。这个
AKsv
和
64bit
的随机数
An
发送到 HDCP
接收器的设备
B。
看下spec给的例子:
0xb70361f714,选0,2,3,6,7,…,38,0x511ef21acd选2,4,8,9,10,…39,结果相加,写了个c代码验证,如下:
#include<stdio.h> int main() { unsigned long long k[20] = {0x4da4588f131e69, 0x8a6a47abb9980d, 0xf3181b52cbc5ca, 0xa0d064c8112c41, 0xb39d5a, 0x91a47b4a6ce4f6, 0x8c7fb706ee3fa0, 0xc02d8c9d7cbc28, 0x482f8e, 0xe2db3a54, 0x4d581aede66125, 0xbf7b22f7, 0xf61bce6b, 0xa1ed49f9, 0xc98e9dd, 0x20c, 0xceac4fc3, 0x54c7ea5bdd7b43, 0x05d3408a78fb01, 0x373b634a2c9e40}; unsigned long long k1[20] = {0x24bf2185a36c60, 0xa72e69c5eb6388, 0x3bd5103, 0x0dd170be, 0x1a748be4866bb1, 0x4bbb037899eea1, 0x190ecf9cc095a9, 0xa821cf, 0x1a8a0bc4298a41, 0xaefc0853e62082, 0xe3053fa3e9fa69, 0x37dc7d1, 0x9e93d41e0811f7, 0x2ceec6c, 0xdf6d, 0xca31a5f, 0x1d30e8cb198e6f, 0xcec7ec09245b43, 0xb08129efedd583, 0xedeef9d099b78c}; unsigned long long sum = 0; for (int i = 0; i < 20; i++) { sum = (sum + k[i]) & 0xffffffffffffff; } printf("sum = 0x%llx\n", sum); unsigned long long sum1 = 0; for (int i = 0; i < 20; i++) { sum1 = (sum1 + k1[i]) & 0xffffffffffffff; } printf("sum1 = 0x%llx\n", sum1); }
可以看到,算出来的结果相等且同spec一致
计算出km之后,根据km,repeat和An算ks,m0和r0,验证r0和rx端读到的值是不是相等,相等则继续,不等则失败。以上是第一阶段的流程。
2.1.2 hdcp1.4第二阶段
HDCP 的接收器是一个 HDCP 中继器的时候需要第二阶段的认证,只有 REPEATER 位被置上表明下游设备是一个 HDCP 中继器的时候,HDCP 的发 送器才会执行第二阶段的认证协议。在这个阶段通过一个 HDCP 的连接树,收集下游所有连接到 HDCP 中继器设备的 Ksv 列表。HDCP 中继器下游保护的 HDCP 接口端口完成和它连接的所有 HDCP 接收 设备的认证协协议之后,HDCP 中继器会收集一个它所连接的 HDCP 接收器的列表。这 个列表为一个连续的字节序列,每个 Ksv 占据 5 个字节,即 40 个 bit,按照小端的方式 排列。这个字节序列的长度为下游连接的包括 HDCP 中继器在内的 HDCP 设备的数量 的 5 倍字节。一个 HDCP 保护的接口端口如果没有活动的设备连接,那么它下面连接的 的设备不会有任何信息加入到这个列表。当然,在任何一级上的 HDCP 中继器上的 KSV 列表都不包括 HDCP 中继器本身。如果一个 HDCP 保护的接口端口连接的是一个 HDCP 接收器而不是一个 HDCP 中继器,那么就把 BKsv 加入到列表当中。如果一个 HDCP 保 护的接口端口连接的是一个 HDCP 中继器,那么就把下游 HDCP 中继器的 Ksv 列表加 入到当前列表,在加上这个下游的 HDCP 中继器的本身的Ksv。
发送器通过计算
V
的
SHA-1
哈希值 来验证 KSV
列表的完整性。如果这个被
SHA-1
哈希出来的值
V
不等于读取回来的 HDCP 中继器端计算的
SHA-1
哈希值
V
’,那么认证的协议会失败退出。如果
READY 状态位的有效位没有在最大可允许的 5
秒内使能,对
HDCP
中继器的认证失败。当认 证失败时,HDCP
的发送器从
HDCP
中继器的认证中退出,通信结束。当然,认证可以
HDCP
发送器向接收器发送一个
An
和
Aksv
来随时重新进行,也就是是说重新 进行第一阶段的认证。
安全哈希算法(Secure Hash Algorithm)是主要应用于数字签名标准领域定义的数字签名算法。SHA1有如下特性:不能从消息摘要中复原信息;两个不同的消息不会产生同样的消息摘要。任何输入消息的变化,哪怕仅有一位,都将导致散列结果的明显变化。
HDCP协议中V(V’)计算如下:V(V’)=SHA1(ksv_list||binfo||Mo(Mo’))。
KSV list存储于Repeater DPCD地址0x6802C~0x6803A的FIFO中,FIFO中有15字节,每个设备的KSV是40比特,也就是5字节,所以 FIFO中每次读取出来的是3个设备KSV。HDCP的Repeater最多支持下游有127个设备,也就是说FIFO最多需要读取127/3次。每次读取完后硬件会自动清掉被读走的数据,同时用下一组KSV填满。Binfo是存储下游设备拓扑结构的16比特数据,包括拓扑深度等。Mo(Mo’)是 64比特的私钥。也就是说计算V(V’)时,系统传输给SHA1的消息长度最大为127×40+16+64=5160(0x1428H)比特,对于长度小于2^64(0x000H)位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。在传输的过程中,数据很可能会发生变化,这时候就会产生不同的消息摘要。 SHA1算法只接收位输入。字符串“KSV list||Binf||M0”消息摘要需转换成位字符串如下:0 0 0……0(5160位),SHA1根据这个消息来计算MD5。
2.1.3 hdcp认证第三阶段
Ki,类似Ks,56bits,用于HDCP cipher对HDCP内容加密、解密。Mi,一个新的64bits 随机数,由加密函数生成,Ri,16bits,用于链路完整性检查,每128frame时更新一次。ransmitter和Receiver各自计算出 (Ki, Mi, Ri)还是通过hdcpBlockCipher计算出来。检测两端ri相不相等。
2.2 代码注解
的加密机是整个
HDCP
系统的核心,完成
HDCP
加密机的设计等于完成了 HDCP 认证和数据加密的基础,重点研究它有很大的意义。总的来说,
HDCP
加密机 (cipher)是一个特殊用途的加密机专门设计用来保证认证协议的的健壮性,同时满足对高 速的无压缩视频流作加密的需要。
加密机从总体结构上看可以分为
3
层。 第一层由 4
个线形反馈寄存器组组成最终得到一个位输出。在
Rekey
信号使能的情 况下,这个一位输出被送入中间层。 中间层有两个相类似的结构组成,其中的一半为由 3
个
28
位的寄存器
Bx
,
By
,
Bz 组成轮函数 B
。而另一半使用类似轮函数的结构,只是在每个时钟脉冲的时候提供一个 轮密钥给轮函数 B
,这个轮密钥的输入来自第
28
位的
Ky
。 最底层把轮函数的 By
,
Bz
,
Ky
,
Kz
作为
4
个
28bit
的输入,通过一个压缩函数在每个时钟周期产生一个 24
位的伪随机数,可以清楚地看出这个
24 bit
的值就是一个不 断变化的流加密密钥,和真正的数据进行异或以后在用同样的方式解密
。注意到这个随机数是以时钟为单位不断随机变化的,这就加大了攻击和激活成功教程的难度。
2.2.1 基本模块接口
hdcpBlockCipher
的功能。具体由多个函数构成,
BlockModule
函数负责完成 block模块里面的计算,又分为
RoundFunction
和
RoundFunctionK
分别负责
block
模块里面轮函数 B
,
K
的计算。
LFSRModule_init
函数负责完成线形反馈寄存器模块的计算 和初始化。在认证期间,HDCPBlockCiper
的输入为
Km
,
An
,
REAPETER
。输出为
Ks
。 在垂直消隐期内,HDCPBlockCiper
的输入为
Ks
。软件代码如下:
,在每个加密桢之前的垂 直消隐期内建立帧密钥 Ki
。
的操作过程在加密机里面分为以下几个步骤:
block
模块加载
B
和
K
寄存器
Block
模块里面运行
48
个时钟周期
hdcpBlockCipher
B
寄存器的最低
56
个
bit
作为以后要使用的
Ks
或者
Ki
B
寄存器的
84
个
bit
的值送入
K
寄存器
B
寄存器
Ks
或者
Ki
block
模块运行
56
个时钟周期后保存最后
4
个
clock
里
64 bit
的
Mi
x
,
y
,
z
由低位到高位一次组成了
B
,
K
的轮寄存器。当轮寄存器的输出 小于 84
个
bit
的时候,最低有效位被使用,其他的未被使用的被置为零。比如,
65 bit 的 REPEAT
位和
An
的组合,被加载到
Bx
,
By
寄存器和
Bz
寄存器的从最低有效位开 始的 9
个
bit
,加起来正好
65
个
bit
。而
Bz
寄存器的从最高有效位开始的
19
个
bit
都 被置为零。与之类似的从 Bx
和
By
在
hdcpBlockCipher
的认证阶段
6-9
的时候从最低有 效位的 56 bit
保存为
Ks
或者
Ki
。 可以看出在第八步运行到第 53
个时钟的时候开始输出
Mi
的最高有效位的前
16
位, 以后依次处处了 Mi
,
Ri
的值,在第
56
个周期的时候最终确定和
Mi
,
Ri
的所有
64 bit 的值。
TMDS
数据使能信号所定义的每个视频像素数据,包括信息包数据都被加密 输出一个 24 bit
的数据,在这个状态下,
LFSR
和
Block
都处于工作状态,但是
rekey 使能信号无效。
hdcpRekeyCipher
通过
LFSR
模块把新的密钥装入 Block
模块。在
rekey
期间,没有其他的对于加密机状态的初始化,也没有 任何从加密机的输出。LFSR
和
Block
模块运行
56
个周期,在此期间,
rekey
使能信号为1
。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/132734.html