百度空间 | 百度首页 
 
查看文章
 
飞信分析之九:飞信登录时的身份验证
2007年09月20日 20:41
作者:nathan

好久没搞这个了,现在根据一些朋友提出的问题继续分析好了。:)

飞信的整个登录过程包括取系统配置、验证身分、取联系人、取离线消息等等一堆过程,这里就不细述了,下面主要说明到是一些朋友比较关心的身份验证是怎么做的。

飞信有两处验证身份,第一次是通过SSL向SSIPortal登录时,第二次是用SIP协议向Proxy Server注册时。

一、向SSIPortal登录

SSI是啥,我一直没弄明白,是Single Sign-In? 习惯上不是SSO(Single Sign-On)吗?反正飞信一开始,必须向nav.fetion.com.cn登录,这是飞信的Portal。登录过程其实很简单,就是通过SSL做一个的GET,请求是:
    https://nav.fetion.com.cn/ssiportal/SSIAppSignIn.aspx?mobileno=13XXXXXXXXX&pwd=XXXX
pwd就是这个用户的密码。服务器验证通过后,就会返回200 OK,Cookie中就有关键的SSIC了。SSIC应该是服务器给客户端的Credential,以后再跟服务器以Http的方式打交道,就必须带上这个Credential了,如下一步的可选操作Geturi:
    POST /hds/geturi.aspx HTTP/1.1
    User-Agent: IIC2.0/PC 2.1.0.0
    Host: 221.130.45.205
    Cookie: ssic=xxxxxxxxxxxxxxxx
    Content-Length: 0
    Connection: Keep-Alive

如果采用http方式而非tcp直连方式(连proxy server的8080端口),那么与服务器间的sip协议是用http承载的,每次都必须带上这个ssic。

这次登录除获得Credential外,还一个重要的作用就是获得用户的URI,即"sip:123456789@fetion.com.cn;p=xxxx".

二、向Proxy Server注册
完成上一步,就开始SIPC的交互过程了,首先用Register方法向Proxy Server注册,Proxy Server的地址(221.130.45.203)从哪来的,以前文章专门说过。

注册的过程是:
-----------------------------------------------------
xxx.xxx.xxx.xxx:xxx >>>>>>>> 221.130.45.203:8080

R fetion.com.cn SIP-C/2.0
F: 123456789
I: 1
Q: 1 R
L: 249

<args>.......</args>
-----------------------------------------------------
xxx.xxx.xxx.xxx:xxxx <<<<<<<< 221.130.45.203:8080

SIP-C/2.0 401 Unauthorized
I: 1
Q: 1 R
W: Digest algorithm="MD5-sess",nonce="xxxxxxxxxxxxxxxx"

-----------------------------------------------------
xxx.xxx.xxx.xxx:xxxx >>>>>>>> 221.130.45.203:8080

R fetion.com.cn SIP-C/2.0
F: 123456789
I: 1
Q: 2 R
A: Digest response="xxxxxxxxxxxxxxx",cnonce="xxxxxxxxxxxxxxxx"
L: 249

<args>......</args>
-----------------------------------------------------
xxx.xxx.xxx.xxx:xxxx <<<<<<<< 221.130.45.203:8080

SIP-C/2.0 200 OK
I: 1
Q: 2 R
X: 600
L: 877

<results>.....</results>


这是个标准的Digest Authentication验证过程,具体去看SIP或HTTP的文档好了:) 我们来关心"W"即WWWAuthenticate这个SIP Header Field,nonce是服务器给出的,那response和cnonce是怎么计算出来的呢?

计算response和cnonce需要用到sid(飞信号)、password、domain(fetion.com.cn或vodafone等用户所属域)、nonce。飞信计算cnonce是用了4个随机数组成一个16进制的字符串然后求这个字符串的MD5,responce的计算方法是:
1.求"sid:domain:passwd"这个utf8字符串的MD5值,得出key
2.求"key:nonce:cnonce"这个utf8字符串的MD5字符串,得出H1
3.求“REGISTER:sid"这个utf8字符串的MD5字符串,得出H2
4.求"H1:nonce:H2"这个utf8字符串的MD5字符串,即为response.


以上就是飞信的身分验证过程,我还没来得及写代码测试,应该就是这样子。另外,如果知道用户的URI,是否可以不用注册到SSIPortal?这个需要测试才知道,我看飞信中好象还对注册到SSIPortal的Session做了Keep Logon。

好啦,分析到现在我们可以做一个飞信的客户端了,哈,谁有兴趣? ;)

类别:飞信协议分析 | 添加到搜藏 | 浏览() | 评论 (74)
 
最近读者:
 
网友评论:
1
2007年09月24日 22:26 | 回复
有个代码网站上有sip-c 1.0的手机客户端协议,不过与现在的sip-c协议不是一样的.有兴趣一起研究一下.谢谢.
 
2
2007年09月24日 22:29 | 回复
中秋快乐!能否介绍一下整个协议分析的过程,包括使用什么工具,例如如何分析注册,登陆,在线信息更新,好友消息,注销登录==。
 
3
2007年09月25日 01:12 | 回复
你说的手机客户端的协议在哪里? 我用的分析工具也就是是reflector和sniffer而已。
 
4
2007年09月25日 13:36 | 回复
飞信Symbian客户端接口规范.doc 在,WWW.PUDN.COM里面,也就是 http://www.programsalon.com/#
 
5
2007年09月25日 13:45 | 回复
系统使用一个简化和增强的SIP协议:SIP-C(Compact SIP),以适应移动终端设备的接入特点,但SIP及相关协议确立的会话的逻辑过程保持不变。 凡是[RFC3261]要求必须有,但本规范没有要求的消息头,以本规范为准。 本规范有定义的消息头的生成规则以本规范为准。 本规范未定义的消息头的生成规则以[RFC3261]为准。
 
6
2007年09月25日 14:28 | 回复
你怎么猜测得那么准? key = MD5 (SID + “:” + Domain + “:” + Password) H1 = MD5ToHex (key + “:” + n-value + “:” + cn-value) H2 = MD5ToHex (“REGISTER” + “:” + SID) Response = MD5ToHex (H1 + “:” + n-value + “:” + H2)
 
7
2007年09月25日 17:00 | 回复
呵,这个显然不是猜得出的的嘛。你说的那个手机协议的文档我下不了.....
 
8
2007年10月04日 03:45 | 回复
希望能合作开发一个fetion的客户端, 最好将来移植到libpurple上去, 联系方式:abstractid@gmail.com
 
9
2007年10月10日 13:11 | 回复
呵,gaim我不太熟啊,好多年不玩linux了...
 
10
2007年10月10日 16:35 | 回复
md5值和md5字符串有什么区别?我不太懂 我的qq:23382359 有兴趣探讨
 
11
2007年10月10日 21:59 | 回复
我用ruby程序验证求W的response这个步骤,但是结果和抓的码流中的response总不一样,不知道是哪里错了? 我用的是最新的飞信版本。 nathan2007是否验证过这个算法?可否贴出代码? 我想在想开发一个ruby客户端程序,第一步可以通过命令行发送短信给联系人,现在在验证这步过不去。
 
12
2007年10月11日 17:03 | 回复
已经验证发现,只需要ssic,即楼主所说的第一步验证,就能发送SMS了。 很简单就能做出一个通过Fetion来发送SMS的客户端,快搞定了。
 
13
2007年10月11日 21:34 | 回复
to 胖老鹰 这个算法应该是没问题的啦,我没有写代码验证,最近没时间。我文章中把这个算法写得很清楚了,应该比较容易写的吧。 to Yonsm: 哦?那就不用登录到Portal了,假如已经有所有参数的话。
 
14
2007年10月11日 21:38 | 回复
MD5字符串就是MD5的16进制字符串啊
 
15
2007年10月11日 22:00 | 回复
算法已经搞定了,ruby默认的md5的hex值是小写的,改成大写就可以了 不过,我跟踪码流,短消息是通过sip proxy server发送的,而与sip proxy server的连接必需要通过第二步才行啊 为什么知道ssic就可以了呢?难道可以直接通过ssiportal发短信?或者sip proxy的承载为http的时候,不需要第二步的注册步骤吗?
 
16
2007年10月11日 23:03 | 回复
to 胖老鹰: 知道ssic就可以跟portal交互了啊,ssic本就是portal返回的Credential。是,好象是必须向proxy server做注册的,不管是http还是tcp直连。 to Yonsm:不好意思,上面的回复我写错了,飞信的这些东西被我放了一段时间又快忘光了 :P。有SSIC以后,通过HTTP承载还是要向proxy登录的吧? ,我文章中写了的,如果有所有参数的话,应该是直接试试不要SSIC直接向proxy server作Register
 
17
2007年10月12日 10:45 | 回复
Nathan,我在测试中似乎发现一个问题,Fetion 在向 Proxy Server Post 的时候有个 Pragma: 值,好像,这个值是有什么关系的,否则会说Bad Request。 可否向 nathan MSN 请教?Yonsm@msn.com
 
18
2007年10月12日 12:49 | 回复
Pragma 随便写就可以 ssic的加密方式是什么?谁知道?
 
19
2007年10月12日 14:26 | 回复
已经完成了发短信的ruby客户端,确认在使用tcp直连时不需要注册ssiportal的步骤(只需要执行一次,知道用户uri即可),可以直接通过tcp连接proxy server,注册成功后可以通过M消息发送短信,但是这种方式目前只能给你的联系人发短信,不能给自己发,看来给自己发短信使用的不同的方式,这个有待抓码流进一步确认。
 
20
2007年10月12日 14:31 | 回复
To sc0698: 已经发现了,好像是标识客户端Session的,前面是六个字母,后面是一个GUID字符串。我每次登录用CoCreateGuid生成一个就是了。 To Nathan,我昨天搞错了,确实应该老老实实地按照你本文所说的方法去登录:)
 
21
2007年10月12日 18:23 | 回复
Pragma是Http协议规定的标准的Header中的一个
 
22
2007年10月13日 11:13 | 回复
发现通过fetion给自己发短信也是使用Message消息,但是To字段不一样,给联系人发短信使用的是T: tel:phonenumber;而给自己发短信使用的是T: sip:sip_uri。
 
23
2007年10月13日 19:12 | 回复
各位网友,既然大家对飞信那么多兴趣,可以加入这个Q群:10520741,大家一起研究交流. 暗号是fetion.
 
25
2007年10月15日 07:17 | 回复
博主,是否能实现在网页上直接进行飞信发送信息?有办法吗?
 
26
2007年10月18日 14:46 | 回复
飞信2008版本(v3.0)的群功能比较差,而且还是比较界面更不好用.垃圾.
 
27
2007年10月20日 16:27 | 回复
key = MD5 (SID + “:” + Domain + “:” + Password) H1 = MD5ToHex (key + “:” + n-value + “:” + cn-value) H2 = MD5ToHex (“REGISTER” + “:” + SID) Response = MD5ToHex (H1 + “:” + n-value + “:” + H2) 第一个个公式计算出来的key值是一个16字节长度的数,那么第二个公式中的key是如何和后面的字符串相加的呢? 请达人解惑!?
 
28
2007年10月21日 09:50 | 回复
是可以的. 先把“:” + n-value + “:” + cn-value组合成一个String 然后把这个String进行getBytes(),然后两个bytes[] copy 在一起做md5tohex.
 
29
2007年11月04日 11:21 | 回复
提供飞信程序破解服务,有需要的联系java_zhi_wei@sina.com
 
30
2007年11月04日 15:06 | 回复
A: Digest response="xxxxxxxxxxxxxxx",cnonce="xxxxxxxxxxxxxxxx" 这部怎么都通不过去。每次提交还是返回 W: Digest algorithm="MD5-sess",nonce="xxxxxxxxxxxxxxx" 唉。我检查过算法,正确的。不知道哪里错了- -!
 
31
2007年11月04日 15:56 | 回复
问题已解决了. HTTP POST 要按步骤… 1. SIPP 2. R fetion.com.cn SIP-C/2.0 (一) 3. SIPP (返回nonce) 4. R fetion.com.cn SIP-C/2.0 (二, 提交 response) 5. SIPP (成功则返回200) 就可以发 SMS 了
 
32
2007年11月10日 01:08 | 回复
你好:我问个不该问的问题,看了楼主的文章,我知道了去使用sniffer去分析网络协议,但我用它的时候查看包内容不能显示utf8格式的数据,不知道你们是怎么去看这些数据的,能给个提示吗?? 谢谢
 
33
2007年11月17日 11:38 | 回复
Pragma: xz4BBcVcca37cd0-440f-45ce-bdd0-9e1034ab284e 前面是一样的"xz4BBcV" 后面的是guid?怎么算出来有人知道吗? 和手机客户端的guid是否同样的算法?
 
34
2007年11月19日 15:38 | 回复
提供飞信PC客户端协议模拟程序. QQ:294901463
 
35
2007年11月21日 09:28 | 回复
请教takwai: HTTP POST 要按步骤… 1. SIPP 2. R fetion.com.cn SIP-C/2.0 (一) 3. SIPP (返回nonce) 4. R fetion.com.cn SIP-C/2.0 (二, 提交 response) 5. SIPP (成功则返回200) 就可以发 SMS 了 你说的这些步骤是用HTTP还是用SIP协议实现?
 
37
2007年12月01日 22:54 | 回复
沮丧中 按照Nathan的提示,发送tcp消息 http = Net::HTTP.new('221.130.45.208', 8080) 消息内容: data = < END_DATA 怎么一点响应都没有啊?
 
38
2008年01月25日 15:20 | 回复
向SSIPortal登录 这一步我一直搞不懂你是怎么知道的,我抓了包,但是数据是加密过得,什么都看不出来。 可不可以说下心得?
 
39
2008年01月25日 15:52 | 回复
上面那个问题是我提的。 SSIPortal 认证过程的数据是加密的,用 Omnipeek 分析看不到什么有用的东西。 博主在文中分析出来的那些信息不知道是如何得来的,我是把源码反编译了,在一点点的查询搜索。 博主可否告知?
 
40
2008年02月02日 23:17 | 回复
请问楼主,pidgin的飞信插件,允许用户与非好友发送即是信息,这是怎么回事?
 
41
2008年02月03日 15:47 | 回复
成功实现了登录功能,其中的 response 和 cnone 的生成都是直接用从 fetion客户端反编译出来的代码,太方便了。 幸好飞信是用c#写的,不然要是用c++或delphi,那反编译出来的就是天书了。
 
42
2008年03月03日 13:08 | 回复
请问搂主,在我的程序与ProxyServer认证交互的过程,总返回401 Unauthorized,是为什么? Digest Reponse已经反复用从Fetion截获的数据对照计算过,计算应该没有错。 下面是程序向SSIPortal登录过后,继续与ProxyServer认证的过程: CLIENT --> 221.130.46.141:8080 R fetion.com.cn SIP-C/2.0 F: 598728312 I: 1 Q: 1 R L: 252 CLIENT <-- 221.130.46.141:8080 SIP-C/2.0 401 Unauthorized I: 1 Q: 1 R W: Digest algorithm="MD5-sess;SHA1-sess",nonce="1E3A1F3A732128AC52144B0B52C12347" (to be continue)
 
43
2008年03月03日 13:08 | 回复
CLIENT --> 221.130.46.141:8080 R fetion.com.cn SIP-C/2.0 F: 598728312 I: 1 Q: 2 R A: Digest response="C1F5D92BB2A28C10438D0D2E0F9EB383",cnonce="9E63464B273DD1C3CD3E1E257EC2D235" L: 252 CLIENT <-- 221.130.46.141:8080 SIP-C/2.0 401 Unauthorized I: 1 Q: 1 R W: Digest algorithm="MD5-sess;SHA1-sess",nonce="3C2894706AEC91F437337A274EFD4CF8" 显然服务器认为不通过,再给了一次nonce值。这就奇怪了,我漏了其他步骤吗?
 
44
2008年03月04日 12:03 | 回复
OK,通过了。 对不起,原来我给我的程序欺骗了。
 
45
2008年03月11日 13:51 | 回复
大家都是用什么语言写的?我用vc++模拟登陆的第一步验证的时候总是返回bad request,我就是用ssl连上服务器了,发请求的时候把密码进行了utf8转换和url转换,但一直不能成功,我是刚接触这块,比较菜,希望大家能指点下,多谢!
 
46
2008年03月14日 02:50 | 回复
我等待大侠门的Fetion类哈~~
 
47
2008年03月19日 13:04 | 回复
to hanphy: huh???怎么解决的?我也是服务器验证不通过,又给了个nonce...
 
48
2008年03月20日 09:01 | 回复
timo,就是那样弄啊。不过文档讲不清楚,我试了好久才试出来。 干脆分享一下: public string GetDigestResponse() { Encoding enc = Encoding.ASCII; string encstring; MD5 md5 = MD5.Create(); encstring = sid + ":" + domain + ":" + loginPassword; byte[] b_key = md5.ComputeHash(enc.GetBytes(encstring)); byte[] b_nvalue = enc.GetBytes(n_value); byte[] b_cnvalue = enc.GetBytes(cn_value); byte[] step1hash = new byte[b_key.Length + b_nvalue.Length + b_cnvalue.Length + 2];
 
49
2008年03月20日 09:01 | 回复
int i_all = 0; for (int i = 0; i < b_key.Length; i++) step1hash[i_all++] = b_key[i]; step1hash[i_all++] = (byte)':'; for (int i = 0; i < b_nvalue.Length; i++) step1hash[i_all++] = b_nvalue[i]; step1hash[i_all++] = (byte)':'; for (int i = 0; i < b_cnvalue.Length; i++) step1hash[i_all++] = b_cnvalue[i]; byte[] hash = md5.ComputeHash(step1hash); string h1 = StringUtils.bytes2hexstr(hash); encstring = "REGISTER" + ":" + sid; hash = md5.ComputeHash(enc.GetBytes(encstring)); string h2 = StringUtils.bytes2hexstr(hash); encstring = h1 + ":" + n_value + ":" + h2; hash = md5.ComputeHash(enc.GetBytes(encstring)); digestResponse = StringUtils.bytes2hexstr(hash); return digestResponse; } 我在做Fetion的API,看能不能搞得定。
 
50
2008年03月21日 07:35 | 回复
oh... 谢谢啊,关键是md5和md5hex的问题。 我写的是php, md5有两种模式,所以搞错了。 已经解决了。 谢谢啊, function calc_response($sid, $domain, $password, $nonce, $cnonce) { if(empty($sid) || empty($domain) || empty($password) || empty($nonce) || empty($cnonce)) die("error when calculating response digest"); $key = md5("{$sid}:{$domain}:{$password}", true); $h1 = strtoupper(md5("{$key}:{$nonce}:{$cnonce}")); $h2 = strtoupper(md5("REGISTER:{$sid}")); $response = strtoupper(md5("{$h1}:{$nonce}:{$h2}")); return $response; }
 
51
2008年04月01日 09:45 | 回复
to:hanphy 这个loginPassword是不是就是登录的密码,不是加密过的吧,是直接用户输入的吧
 
52
2008年04月02日 11:14 | 回复
配置文件里的http-tunnel可以用来做http模式的Digest Authentication么? 那到底怎么用http模式?nathan能解答一下么?谢谢
 
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码: 请点击后输入四位验证码,字母不区分大小写
      

     

©2009 Baidu