飞信2010身份验证算法成功破解
周末简单抓包分析了一下飞信的登录协议,昨天晚上一直延续到现在都在研究它的身份验证的算法,身份验证的过程大体搞清楚了,跟旧版本的形式差不多,最大的变化是2010不再是将密码的散列值进行传输,而是使用RSA非对称加密之后再进行传输。
在SipC注册的过程中,客户端生成一个CNOUCE,然后发给服务器,服务器自己生成一对密钥,私钥自己保留,公钥放到key里面发给客户端,随同公钥一起发给客户端的还有服务器生成的key值,和一个数据签名signature。
客户端的加密过程如下:
客户端将三个字段的UTF8数组合并成一个byte[](在C里面也就是unsigned char*),然后对这个byte[]进行RSA加密,加密使用了PKCS#1 1.5的padding方式,查了一下.net只支持两种padding,相比于no padding来说更安全一些,而且它每次加密之后的结果都是不一样的,另外使用这种Padding进行加密时,要加密的数据至少要比密钥的模长短至少11个字节,否则就会加密失败。
下面说一下是将哪三个字段加密了,第一个字段是服务器发过来的nonce,第二个字段是密码,第三个字段是一个aeskey。
nonce这个没什么好说的,就是Sipc注册的时候返回来的nonce值,直接放在前面就可以了。
password是这个是困扰我时间最长的,飞信在计算response值的时候,把这三个字段当成16进制字符串,也就是类似于”ACFDF768597″这种,它将它们转换成UTF8数组,每两个字节转换成一个字节的UTF8数组,但原始密码肯定不可能是这种标准的16进制字符串,必然是做过某种处理,注意到在发送验证信令的后面附上了一个值algorithm=”SHA1-sess-v4″,然后我意识到密码可能是经过SHA1散列处理了,事实上确实如此,只不过不如我想象的那么简单。在linux下用openssl提供的加密算法来测试,返回的却一直都是Unaccpectable,一直以为是加密算法出了问题,反复修改测试各种加密算法,无数次失败后终于决定回到windows下改用.net测试,用飞信用到的.net framework里提供的加密算法进行加密,确保加密算法没有问题,庆幸自己多掌握了几门语言,虽然写得不如别人漂亮,但能看懂对我来说就足够了。
用.net写了一个sipc验证的程序,结果总是提示密码错误,也就是说密码的处理上确实存在问题,折腾了两三个小时终于弄明白飞信对密码都动了哪些手脚。它将字符串fetion.com.cn:password的utf8字符串进行SHA1做散列,然后得出一个16进制字符串,SHA1是20个字节的,16进制字符串有40个字节,然后再将这个字符串前面再附上一个user-id,再做散列,得到的字符串就是最后要加密的密码,user-id这个东西在旧版本里面我就注意到,但事实上它并没有起到什么作用,新版本里面居然把它用到身份验证里面来了,至于user-id的获取,这个连看也不用看,肯定在SSI登录的完成的时候会在返回的数据包中包含。
再就是aeskey这个字段,这真是个让我哭笑不得的字段,从名字上看上去好像是用到了AES对称加密,事实上在生成这个字段的时候也确实用到了.net关于AES算法的Rijndael类,冒然贴一段代码:
1 2 3 4 5 6 7 | public static string GenerateKey() { Rijndael rijndael = Rijndael.Create(); rijndael.KeySize = 0x100; rijndael.GenerateKey(); return BinaryToHex(rijndael.Key); } |
简单地说一下,第一句话创建一个Rijndael对象,第二句话指定密钥的长度为256个字节,GenerateKey()这个方法在MSDN里面解释是说生成一个随机密钥,仔细查看了.net关于Rijndael的代码,发现它在它的父类中声明,是个抽象方法,而Rijndael类并没有对这个方法进行重写,也就是说这里调用的这个方法是个空方法,我把这个方法注释掉以后再调用这个方法,仍然可以生成随机字符串。最有意思的地方是这里并于AES的只有这几句话,根本没有涉及到任何加密的代码,也就是说飞信开发人员需要一个64字节的随机字符串附在密码后面,一起加密,这样使要加密字符串更长一些,加密的强度也就更大一些,而飞信开发人员嫌麻烦,懒得再重新写一个生成这样一个随机字符串的方法,于是就借用AES里面的随机密钥,其实整个身份验证过程跟AES没有半点关系,即使我把这个aeskey换成了一个固定值如:“4A026855890197CFDF768597D07200B346F3D676411C6F87368B5C2276DCEDD2”也一样能够验证通过,而光是这个名字就给了我很大的误导。
总而言之,飞信2010身份验证算法已经搞定了,在windows下用.net测试也通过了,接下来如何移植到C+openssl就是以后的事了,并于openssl实现这些相关的算法有时间再写吧。
声明:本文纯粹用于学习,不出于任何商业利益或者有任何损坏飞信利益的行为,涉及内容比较抽象,靠此文不可能写出飞信登录程序,希望权威部门不要找我麻烦。
原创文章,转载请注明: 转载自basic coder
本文链接地址: http://basiccoder.com/fetion2010-auth-algorithm.html
xd,最近我在开发php的飞信,遇到一些问题,能请教一下吗?
在v4digest-type=2这一步,就是第二次加密密码的时候,是如何实现的?
我的理解是,fetion.com.cn:密码 sha1一下输出16进制的散列值,然后再转换成10进制的一个字符串。然后userid如何处理,再跟刚才得到的十进制的字符串连接起来呢?不得其解啊。
我qq41204034
灰常期待跟你交流~
(LZ搞错了,AESKEY必须是一个随机字符串,身份验证时客户传给服务器的ASEKEY字段在以后是作为消息内容加密用key的,如果固定,你懂的。。。)