注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

老狗的博客

尽管每一步都很微小,但我确认我在进步

 
 
 

日志

 
 
关于我
sky

认真生活,努力工作 热爱技术,关注DB,存储,分布式,中间层,java,c++,php

网易考拉推荐

mysql server/client communication protocol 【handshake分析】  

2012-05-04 08:34:58|  分类: mysql |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
首先描述下握手的过程:
1. 首先client向server发起并成功建立tcp连接
2. handshake第一步:server向client发出initialization packet,又称greet packet,在这个包中,包含了用于加密的random_seed,共20字节
3. handshake第二步:client用random_seed对于用户输入的密码加密后,并用户名字等,一共发回server
4. handshake第三步:server也用random_seed对于密码进行加密,然后加密结果和client发回的结果进行对比,如果正确发回ok包,如果不正确,发回error包


handshake第一步


sever首先通过tcp连接向client发出greet packet,先在这里给出greet packet的包结构吧

name

bytes

description

protocol_version

1

协议的版本号,比如10,这个值来自于/include/mysql_version.h中的PROTOCOL_VERSION

server_version

null terminated string(前面已经介绍过)

MYSQL_SERVER_VERSION

example value-“4.1.1-alpha”

thread_id

4

id of the server thread for this connection

scramble_buff_part1

8

the password mechanism use this

filler1

1

0x00

server_capabilities

2

 

server_language

1

current server character set number,这个来自于information_schema.collations表的id字段

server_status

2

server_status_xxx flags

filler2

13

always 0x00

scramble_buffer_part2

12

 

filler3

1

0x00


greet packet在后面的用途:
1. server_language,非常有用,用于client端加密密码
2. scramble_buffer_part1,scramble_buffer_part2,这是服务器发送的随机种子
random_seed= scramble_buffer_part1 + scramble_buffer_part2
3. server_capabilities: 用于向client表示服务器端可以提供的功能,具体每个标志位如何表示可以
查看文档

handshake第二步


client在收到server的greet包后,向server进行认证,标明自己是授权用户
包结构如下:

name

bytes

description

client_flags

2

客户端的能力标识

extend_flags

2

扩展标识

max_packet_size

4

0表示客户端没有自己的限制

charset_number

1

字符校验规则编号,对应information_schema.collation里面的id字段

filler

23

0x00

user

null-terminated string

用于校验的用户名

scramble_buff

21

用serverinit packet的scramble_buffer内容对秘密加密过的内容,length coded string

databasename

null-terminated string

数据库名字,可选字段,如果你在client_flags里面声明了,就可以有,否则不能有


scrambe_buff是经过加密后的密码,其类型为【length coded string】
注解:
【length coded string】:a variable-length string. Used instead of Null-Terminated String, especially for character strings which might contain '\0' or might be very long.The first part of a Length Coded Stringis a Length Coded Binary number (the length);the second part of a Length Coded String is the actualdata.
【length coded Binary】:a variable-length number. To compute the value of a Length Coded Binary, onemust examine the value of its first byte

value of first bytes

bytes following

description

0-250

0

第一个字节的值既是这个值

251

0

column value = null,仅仅在row data packet出现

252

2

第一个字节之后16bit的值既是这个值

253

4

第一个字节之后的32-bit值就是这个值

254

8

后面跟着64bit的值就是这个值


packet中scramble buffer的数据怎么计算,可以参照jdbc中的一段加密算法,如下:


public static byte[] scramble411(String password, String seed, Connection conn)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
// java.security.MessageDigest是用来对于数据做签名用的,提供了类似sha-1,sha-256等算法
MessageDigest md = MessageDigest.getInstance("SHA-1");
String passwordEncoding = conn.getPasswordCharacterEncoding();
//首先对于密码做一次sha-1签名,得到passwordHashStage1变量,注意这个地方的passwordEncoding就是server传过来的字符集
byte[] passwordHashStage1 = md.digest((passwordEncoding == null || passwordEncoding.length() == 0) ? 
StringUtils.getBytes(password): StringUtils.getBytes(password, passwordEncoding));
md.reset();
//对于签名后的密码进行再次签名,得到passwordStatge2
byte[] passwordHashStage2 = md.digest(passwordHashStage1);
md.reset();
//得到服务器传递过来的random_string的字节序列
byte[] seedAsBytes = StringUtils.getBytes(seed, "ASCII");
//用random_string的字节序列进行update
md.update(seedAsBytes);
//用签名后的password进行update
md.update(passwordHashStage2);
//最后获得签名
byte[] toBeXord = md.digest();
//对于签名的每个字节和passwordHashStage1的每个字节进行异或操作
int numToXor = toBeXord.length;
for (int i = 0; i < numToXor; i++) {
toBeXord[i] = (byte) (toBeXord[i] ^ passwordHashStage1[i]);
}
return toBeXord;
}

这个加密算法和实际中的是否一致?我们可以来验证下
打开抓包工具ethereal, 抓到我们需要的两个包,greet包和client auth包
mysql server/client communication protocol 【handshake分析】 - sky - 老狗的博客
 用红笔圈起来的便是server端发过来的随机种子,共20字节
byte[] salt = {0x25,0x75,0x41,0x23,0x28,0x41,0x4c,0x3c,0x27,0x4d,0x30,0x47,0x53,0x4d,0x67,0x40,0x4a,0x32,0x5b,0x52};
密码是xxxxxxx, 不好意思,不便公开
String password = "xxxxxxx";
scramble = EncodePassword.scramble411(password, randoms_seed);
将scramble打印出来以后,便是:
mysql server/client communication protocol 【handshake分析】 - sky - 老狗的博客
 
最好,我们用我们计算出来的和抓包的结果对比一下:
mysql server/client communication protocol 【handshake分析】 - sky - 老狗的博客
 
完全一样,证明了上面的描述是正确的

handshake第三步

在server端收到用户的认证包之后,server端进行验证,并根据client端的一些设置对两者之间的通信达成一定协议,然后对向client端发回响应包,响应包有两种:ok包 和 error包,这两种包都属于result packets中的一种,result packets之间的区分,可以通过第一个字节field_count完成

1. ok 包
认证成功,则发回ok包,ok包格式

name

bytes

description

field_count

1

0x00,用来区分包的类型

affected_rows

1-9 length coded binary

受影响的行数

insert_id

1-9 length coded binary

last insert id,如果表的自增列没有变化,则为0

server_status

2

检查是否命令在事务内部

warning_count

2

警告的数目

message

lengthcoded string

消息,可选的,根据包的长度来决定是否存在


2. error包

name

bytes

description

field_count

1

0xff

errno

2

错误号

sqlstate marker

1

#

sqlstate

5

sql状态号

message

n,可选

长度根据包的长度来决定


抓包结果和此是一致的
mysql server/client communication protocol 【handshake分析】 - sky - 老狗的博客

至此handshake过程结束,现在我们可以建立和server的连接了
 

  评论这张
 
阅读(724)| 评论(2)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018