SSH传输层协议细节说明
2014-06-03 17:59阅读:
基于: RFC 4253:The Secure Shell (SSH) Transport Layer Protocol
以及openssh-5.3
RFC 4253描述了SSH2.0传输层协议的握手过程,但是在具体实现中还会遇到一些没有说明清楚的细节问题。对照openssh-5.3版本的源代码,列举一些实现SSH服务端/客户端时会遇到的陷阱和地雷,避免在今后研发中走弯路。
SSH传输层协议所处的位置如下图:
X
在SSH传输层握手过程中,通讯过程如下图:
一些实现的细节问题:
(1)版本协商阶段的报文4-5即为计算唯一哈希标识H = HASH(V_C || V_S || I_C || I_S || K_S|| e || f || K) 中的V_C和V_S。但是在计算H的时候,是要去掉报文中最后的结束符\r\n的。例如对于客户端版本消息“SSH-2.0-OpenSSH_5.3\r\n“
计算H时只取
(见前23个字节)
(2)大数的表示问题
Openssh使用openssl中的BIGNUM结构来表示和计算大数。在导出大数到buffer中时,必须要给最高位
加载中...
内容加载失败,点击此处重试
加载全文
为1的大数补充0x00前缀
比如对于下面的DH密钥交换的服务端公开参数f,其BIGNUM的首字节0xa4,最高位为1,则在使用该大数时(比如计算共享秘密值K时),必须补充前缀0x00
(3)算法协商SSH2_MSG_KEXINIT的问题
不同版本的openssh中支持的算法列表不同,排列的优先顺序也不同。就openssh-5.3版本而言,相比更高版本,它的列表中没有曲线密码算法;相比更低版本,它在密钥交换算法中优先了diffie-hellman-group-exchange-sha256,其摘要使用的是SHA-256。SHA-256的摘要长度为32字节,而低版本使用SHA-1,其摘要长度为20字节。
SSH2_MSG_KEXINIT消息6-7即为计算唯一哈希标识H = HASH(V_C || V_S || I_C || I_S ||K_S || e || f || K)中的I_C和I_S,但是在实现的细节上,并不是把这两个报文直接作为I_C和I_S,而是经过了如下处理:去掉了padding字节,去掉了padding长度,重新计算了packet_length字段。例如如下对于客户端算法协商消息
在计算H的时候I_C变为
比对可以看到,原始报文最末的8字节padding被去掉了,padding_length字节(第五个字节08)被去掉了,消息长度从16进制314变为了30b。
(4)KEXDH_GEX_REQUEST报文包含3个DH密钥交换参数Min、Numbers ofBits、Max,限定了DH选取大质数的长度,比如对于
min = 1024, nbits = 1024, max = 8192的报文
下面1024位的大质数是合格的(注意高位补0x00)
(5)KEXDH_GEX_REPLY报文包含3部分:服务端公钥、服务端DH公开数f和对唯一哈希标识H的签名。
其中服务端公钥部分根据不同非对称算法有所不同,对于rsa算法来说,包含3个参数:算法名称字符串、公开数publicExponent和modulus。
在计算H时,除了上面提到的对V_C、V_S、I_C、I_S的注意事项之外,还要注意:参数K_S是一个嵌套的Length-Value结构;参数K_S和参数e之间有DH密钥交换参数Min、Numbersof Bits、Max(这个和RFC标准中对H的计算公式有出入)。
(6)在握手阶段计算出的唯一哈希标识H被存为session_id,session_id不会被修改,只写入一次。后续重新协商密钥会改变H,但是session_id不变。(比如导出密钥时,计算HASH(K|| H || “A” ||session_id)。在首次握手时H=session_id,以后H可变,session_id不变。)
(7)服务端回复的KEXDH_GEX_REPLY可以与NEW_KEYS报文一起发送。WireShark解析有错误,比如
其实最后面16字节不是MAC,而是一个NEW_KEYS消息。
(8)在密钥交换过程中,客户端可以发出消息码对应为Ignore的消息。此时密钥交换过程与上述不同,4个报文简化为2个报文。两种过程的消息码在openssh中定义如下
#define SSH2_MSG_KEXDH_INIT 30
#define SSH2_MSG_KEXDH_REPLY 31
#define SSH2_MSG_KEX_DH_GEX_REQUEST_OLD 30
#define SSH2_MSG_KEX_DH_GEX_GROUP 31
#define SSH2_MSG_KEX_DH_GEX_INIT 32
#define SSH2_MSG_KEX_DH_GEX_REPLY 33
#define SSH2_MSG_KEX_DH_GEX_REQUEST 34
一般流程的密钥协商消息码走下面的31-34,客户端发出Ignore消息后,消息码走上面的30-31。
个人总结,欢迎交流讨论,请勿转载以讹传讹
分享
我的博客
微博
微信
朋友圈
1
N
同时转发到微博
发送
SSH传输层协议细节说明
2014-06-03 17:59阅读:
基于: RFC 4253:The Secure Shell (SSH) Transport Layer Protocol
以及openssh-5.3
RFC 4253描述了SSH2.0传输层协议的握手过程,但是在具体实现中还会遇到一些没有说明清楚的细节问题。对照openssh-5.3版本的源代码,列举一些实现SSH服务端/客户端时会遇到的陷阱和地雷,避免在今后研发中走弯路。
SSH传输层协议所处的位置如下图:
X
在SSH传输层握手过程中,通讯过程如下图:
一些实现的细节问题:
(1)版本协商阶段的报文4-5即为计算唯一哈希标识H = HASH(V_C || V_S || I_C || I_S || K_S|| e || f || K) 中的V_C和V_S。但是在计算H的时候,是要去掉报文中最后的结束符\r\n的。例如对于客户端版本消息“SSH-2.0-OpenSSH_5.3\r\n“
计算H时只取
(见前23个字节)
(2)大数的表示问题
Openssh使用openssl中的BIGNUM结构来表示和计算大数。在导出大数到buffer中时,必须要给最高位
加载中...
内容加载失败,点击此处重试
加载全文
为1的大数补充0x00前缀
比如对于下面的DH密钥交换的服务端公开参数f,其BIGNUM的首字节0xa4,最高位为1,则在使用该大数时(比如计算共享秘密值K时),必须补充前缀0x00
(3)算法协商SSH2_MSG_KEXINIT的问题
不同版本的openssh中支持的算法列表不同,排列的优先顺序也不同。就openssh-5.3版本而言,相比更高版本,它的列表中没有曲线密码算法;相比更低版本,它在密钥交换算法中优先了diffie-hellman-group-exchange-sha256,其摘要使用的是SHA-256。SHA-256的摘要长度为32字节,而低版本使用SHA-1,其摘要长度为20字节。
SSH2_MSG_KEXINIT消息6-7即为计算唯一哈希标识H = HASH(V_C || V_S || I_C || I_S ||K_S || e || f || K)中的I_C和I_S,但是在实现的细节上,并不是把这两个报文直接作为I_C和I_S,而是经过了如下处理:去掉了padding字节,去掉了padding长度,重新计算了packet_length字段。例如如下对于客户端算法协商消息
在计算H的时候I_C变为
比对可以看到,原始报文最末的8字节padding被去掉了,padding_length字节(第五个字节08)被去掉了,消息长度从16进制314变为了30b。
(4)KEXDH_GEX_REQUEST报文包含3个DH密钥交换参数Min、Numbers ofBits、Max,限定了DH选取大质数的长度,比如对于
min = 1024, nbits = 1024, max = 8192的报文
下面1024位的大质数是合格的(注意高位补0x00)
(5)KEXDH_GEX_REPLY报文包含3部分:服务端公钥、服务端DH公开数f和对唯一哈希标识H的签名。
其中服务端公钥部分根据不同非对称算法有所不同,对于rsa算法来说,包含3个参数:算法名称字符串、公开数publicExponent和modulus。
在计算H时,除了上面提到的对V_C、V_S、I_C、I_S的注意事项之外,还要注意:参数K_S是一个嵌套的Length-Value结构;参数K_S和参数e之间有DH密钥交换参数Min、Numbersof Bits、Max(这个和RFC标准中对H的计算公式有出入)。
(6)在握手阶段计算出的唯一哈希标识H被存为session_id,session_id不会被修改,只写入一次。后续重新协商密钥会改变H,但是session_id不变。(比如导出密钥时,计算HASH(K|| H || “A” ||session_id)。在首次握手时H=session_id,以后H可变,session_id不变。)
(7)服务端回复的KEXDH_GEX_REPLY可以与NEW_KEYS报文一起发送。WireShark解析有错误,比如
其实最后面16字节不是MAC,而是一个NEW_KEYS消息。
(8)在密钥交换过程中,客户端可以发出消息码对应为Ignore的消息。此时密钥交换过程与上述不同,4个报文简化为2个报文。两种过程的消息码在openssh中定义如下
#define SSH2_MSG_KEXDH_INIT 30
#define SSH2_MSG_KEXDH_REPLY 31
#define SSH2_MSG_KEX_DH_GEX_REQUEST_OLD 30
#define SSH2_MSG_KEX_DH_GEX_GROUP 31
#define SSH2_MSG_KEX_DH_GEX_INIT 32
#define SSH2_MSG_KEX_DH_GEX_REPLY 33
#define SSH2_MSG_KEX_DH_GEX_REQUEST 34
一般流程的密钥协商消息码走下面的31-34,客户端发出Ignore消息后,消息码走上面的30-31。
个人总结,欢迎交流讨论,请勿转载以讹传讹
分享
我的博客
微博
微信
朋友圈
1
N
同时转发到微博
发送