异想天开

What's the true meaning of light, Could you tell me why

rtmfp协议四次握手

日期:2014-10-26 10:34:54
  
最后更新日期:2014-11-28 11:23:13
【技术】
1.rtmfp包服务端解密 server接收到一个服务包后,根据前三个unsigned int类型的整数,计算sessionid。rtmfp协议利用sessionid来分用会话。若sessionid为0,则为握手包。否则则已经建立的会话。用已知的密钥-“Adobe Systems 02”从第4个字节开始解密。接着跟一个short(两个字节),做crc效验。后面描述的就是平坦格式的包。加密算法为cbc模式的aes。
2.客户端连接服务端的四次握手 整体框架图,该图来自rtmfp协议rfc文档:
connect 可以看出,握手成功的情景大概为客户端向服务端发一个Ihello包请求建立连接,服务端答复一个Rhello包。接着,客户端发一个Ikey包包含密钥信息,服务端答复一个Rkey包,连接建立。下面用示例解析出包的格式,需要更为详细的字段意思,可以参考rfc文档,或github下载openrtmfp项目代码阅读,rfc协议对加密这块没有详细的介绍,其说法是协议只规定加密的方法,具体怎么看其实现,而openrtmfp就是一种实现,包含了更多的细节。编译后,可以用中间人(man in middle )模式启动的方式,来查看客户端与服务端包的交互过程。

2.1 Ihello包 ihello 30处于的type位置,type为30即为Ihello包。第一个字节是标记字段,如果第一字节的低4位大于C,那么后面跟两个short(两字节)表示时间戳,如果大于8,则只跟一个short字段。这个时间戳,只有16位。第二个方格表示epd的长度,即后面接epd地址长度只有0x1d。即等价于flash client 的rtmfp://p2p.rtmfp.net:8080/。包结尾(7A 27开始到 09 4E)表示client的tag。用来区分此次握手服务器的答复,后续服务端答复包中需要包含该tag。需要说明的是epd里面0A表示client handshake,0f表示p2phandshake。

2.2Rhello包 rhello type为70表示Rhello包。第一个方格10表示tag的长度,第一个括号括起来的hex字符串就是上次Ihello中的client的tag。 第二个括号括起来hex字符串表示服务端的cookie,客户端回复时,需要加上该cookie才合法。第三个括号括起来hex字符串,就是服务端发给客户端用来最终计算密钥的临时数据。该临时数据为77字节,格式为首4个固定字节(\x01\x0A\x41\x0E)+64个随机字节+9个固定字节(\x02\x15\x02\x02\x15\x05\x02\x15\x0E)

2.3Ikey包 ikey type为38表示Ikey包。第二个方格01 19表示包的长度0x119。第三个方格02 00 00 00表示此次会话对客户端而言的sessionid为0x00000002(网络字节序,大端法)。第四个方格40表示cookie长度0x40,cookie的长度好像是个定值。第一个括号括起来的hex字符串表示cookie。第五个方格为变长类型表示客户端的证书长度(如0x81 04 表示 84,即最高位表示是否还有下一字节)。第二个括号括起来的hex字符串表示客户端的证书(公钥),该证书的hash值即为peerid。第六个方格表示接下来的hex字符串的vlu类型的长度。第三个括号括起来的hex字符串表示客户端发给服务端的计算密钥相关的临时数据块。最后一个方格,好像直接忽略掉了。
这里计算加密和解密的密钥计算方法,客户端发过来public key和临时数据块,利用客户端的public key用Diffie-Hellman方法计算出共享的shared key。
然后对服务端而言,就有了shared key ,客户端的临时数据块,当然还有自己产生的临时数据块,
服务端的加密密钥,可以通过两次hash得到:
1.用客户端的public key做密钥,服务端自己的临时数据块,用sha256算法算出hash值。 2.用shared key做密钥,步骤1的hash值为数据块,用sha256算法得到的即加密密钥。 服务端的解密密钥,也是两次hash得到的:
用客户端临时数据块做密钥,客户端的public key做数据,sha256算一次hash
用shared key做密钥,前一步骤hash值,用sha256算一次hash值即为解密密钥
最后,服务端发Rkey包时,将自己的特定数据块发给客户端,即完成了密钥传输的任务。

2.4Rkey包 Rkey Type为78表示rkey包。第一个方格00 92表示packet长度。 第二个方格00 00 00 01表示此次会话对服务端而言的sessionid为1。第三个方格81 0b为vlu类型即长度为8b,后跟一个hex字符串表示服务端的公钥。最后一个方格忽略。