飞信2010身份验证过程及算法详述

本人还是在校学生,由于滤涉世未深,对互联网还心存敬畏,没能像当初分析2006飞信协议的大哥那样洒脱,出于各种顾虑,当初在写飞信登录协议相关的文章的时候,都没详细地阐述登录过程,那篇文章当初也只是做为自己业余爱好的一个总结,却没想会受到大家如此的关注,很多人留言或发邮件问我具体的身份验证过程及算法,我也无暇一一详细解答,后来想了想,互联网应该是一个开放的环境,大家对飞信的关注其实也是为了给更多人提供方便或者学习交流,我想我也无须吝啬,就在这里把详细地身份验证过程阐述一下,仅用于学习交流,希望大家把它用在正途。
另外,我本人也在用业余时间写了一个Linux环境下的 飞信,期待大家的加入,有兴趣的可以在这里留言。
具体身份验证流程我在下面这篇文章里面说得比较详细了,有需要的话可以先阅读一下这篇文章:
http://basiccoder.com/fetion2010-auth-algorithm.html
在里面有两个重要的过程:
1.密码的处理方式。
密码并不是以明文的方式进行加密的,而是用SHA1做了散列之后才进行加密的,散列的过程与2008略有不同,文字表达能力有限,就贴几个C函数吧:
char* hash_password_v1( const unsigned char* b0 , int b0len
                                                                     , const unsigned char* password , int psdlen)    
{
  unsigned char* dst = (unsigned char*)malloc(b0len + psdlen + 1);
  unsigned char tmp[20];
   char* res;
  memset(tmp , 0 , sizeof(tmp));
  memset(dst , 0 , b0len + psdlen + 1);
  memcpy(dst , b0 , b0len);
  memcpy(dst + b0len , password , psdlen);
  SHA_CTX ctx;
  SHA1_Init(&ctx);
  SHA1_Update(&ctx , dst , b0len + psdlen );
  SHA1_Final(tmp , &ctx);
  free(dst);
  res = hextostr(tmp , 20);
   return res;
}
char* hash_password_v2( const char* userid , const char* passwordhex)    
{
   int id = atoi(userid);
   char* res;
  unsigned char* bid = (unsigned char*)(&id);
  unsigned char ubid[4];
   int bpsd_len;
  unsigned char* bpsd = strtohex(passwordhex , &bpsd_len);
  memcpy(ubid , bid , 4);
  res = hash_password_v1(ubid , sizeof(id) , bpsd , bpsd_len);
  free(bpsd);
   return res;
}
char* hash_password_v4( const char* userid , const char* password)
{
   const char* domain = "fetion.com.cn:";
   char *res , *dst;
  unsigned char* udomain = (unsigned char*)malloc(strlen(domain));
  unsigned char* upassword = (unsigned char*)malloc(strlen(password));
  memset(udomain , 0 , strlen(domain));
  memcpy(udomain , (unsigned char*)domain , strlen(domain));
  memset(upassword , 0 , strlen(password));
  memcpy(upassword , (unsigned char*)password , strlen(password));
  res = hash_password_v1(udomain , strlen(domain) , upassword , strlen(password));
  free(udomain);
  free(upassword);
   if(userid == NULL || strlen(userid) == 0)
  {
     return res;
  }
  dst = hash_password_v2(userid , res);
  free(res);
   return dst;
}
第三个函数是用来对密码进行散列处理的函数,输入是userid和密码,这个函数返回一个40字节的16进制字符串。
另外还有两个函数是在unsigned char串和char串之间相互转换:
unsigned char* strtohex( const char* in , int* len)    
{
  unsigned char* out = (unsigned char*)malloc(strlen( in)/2 );
   int i = 0 , j = 0 , k = 0 ,length = 0;
   char tmp[3] = { 0 };
  memset( out , 0 , strlen( in) / 2);
   while(i < ( int)strlen( in))
  {
    tmp[k++] = in[i++];
    tmp[k] = '\0';
     if(k == 2)
    {
       out[j++] = (unsigned char)strtol(tmp , ( char**)NULL , 16);
      k = 0;
      length ++;
    }
  }
   if(len != NULL )
    *len = length;
   return out;
}
char* hextostr( const unsigned char* in , int len)    
{
   char* res = ( char*)malloc(len * 2 + 1);
   int i = 0;
  memset(res , 0 , len * 2 + 1);
   while(i < len)
  {
    sprintf(res + i * 2 , "%02x" , in[i]);
    i ++;
  };
  i = 0;
   while(i < ( int)strlen(res))
  {
    res[i] = toupper(res[i]);
    i ++;
  };
   return res;
}
然后是计算response过程:
/*这当然是不符合语法的,这样写大家应该就能明白*/
unsigned char* response_tmp = (unsigned char*)nonce
                    + strtohex(hashed_password) + strtohex(aedkey);
最后把response_tmp通过服务器发过来的公钥进行RSA加密后得到response,传回服务器就可以通过验证了。
具体的信令格式都是明文,大家自己抓包看就好了,我在这里也就不多说了。

你可能感兴趣的:(飞信,身份验证)