首页 > 翻译 > 两种RTMP的握手协议

两种RTMP的握手协议

2014年6月16日

RTMP握手协议

根据RTMP的文档,RTMP的握手过程为:

下面是握手的数据格式:

其中:
时间1:C发送C1时,C上的时间
时间2:S发送S1时,S上的时间
时间3:S接到C1时,S上的时间
时间4:C接到S1时,S上的时间
(时间2和时间3可能相等)

所以上面的过程写成代码应该是:

(客户端代码)client.c

(服务器代码)server.c

上面的代码是RTMP协议明文的握手协议,但是adobe公司又将上面的协议给扩展成加密的方式,但是握手的顺序没有变,改变仅仅在随机字段的意义。
我们知道上面的C1与S1都存在一个零字段,在修改后的加密协议中这个字段不为零。所以根据该字段的值,服务器可以了解客户端握手协议的版本,以确定继续握手还是中断连接。

握手的明文格式:

其中

版本1:非零。
版本2:非零。

密文1:由C1的明文生成。
密文2:由S1的明文生成。
密文3:根据密文1生成。
密文4:根据密文2生成。

下面是C1的明文格式:
C1:4B(时间1) + 4B(版本1) + 764B(随机数1) + 764B(X1)。
X1:4B(偏移量) + xB(随机数1) + 32B(密文1) + (728-x)B(随机数2) (0 <= x < 728)

下面我来划一幅图

密文1将整个C1/S1划分成了三个部分[0,776+x),[776+x,808+x),[808+x,1536)。这也是整个加密的关键所在。
特殊情形,当x=728时,整个C1/S1分成了两部分:[0,1054),[1054,1536)

加密步骤:
1.构造C1(填充版本)
与明文握手相比,多了一个版本填充,对于C1填充(0x0C, 0x00, 0x0D, 0x0E),对于S1填充(0x0D, 0x0E, 0x0A, 0x0D)。

2.计算x的值。
根据X1的最前面计算x值。计算方法:
/*x: [0 ,728),这里限制x不能取728*/

3.计算并填充密文。
密文长为32,
对于C1来说密钥为”Genuine Adobe Flash Player 001″(30B),
对于S1来说密钥为”Genuine Adobe Flash Media Server 001″(36B).

整个加密函数encrypt_c1s1(char *c1s1,char *key);

C1整个加密过程可以写成下面的代码:

客户端将C0C1发送出去后,将接收服务器发回来的S0S1S2,这时候客户端要对S0S1进行检查,然后根据S2来发送C2。
校验S1的方法很简单,只需要将S1的digest提取来,然后重新对S1进行加密得到密文后与接收到的密文对比,如果一致校验通过,否则关闭连接。

C2/S2主要是对S1/C1的验证,C2/S2的包跟之前不样的地方在于,它的格式在于C1/S1的特例也就是x=728时的C1/S1格式。(严格来讲x是无意义的。)
C2/S2格式:

产生S2/C2的难点在于对S2/C2的key的选择。

关键是c2/s2的密钥的生成。它是由s1/c1的digest二次加密而来,也就是这c2/s2的密钥长度为32。
从C1/S1得到digest后,用各自的public key进行加密后产生的digest做c2s2的key。

(服务器代码)server.c

分类: 翻译 标签:
本文的评论功能被关闭了.