• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 311, comments - 0, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
            在MaNGOS-Zero中認(rèn)證登錄服務(wù)器是已獨(dú)立的進(jìn)程存在的,名字叫realmd,這樣命名可能是和游戲client端根目錄下的realmlist.wtf文件相對應(yīng)。realmd的主要工作是:檢查登錄用戶的合法性,并在合法的情況下完成通信密鑰的交換,最后把游戲邏輯服務(wù)器的地址信息列表傳給client端。

            realmd認(rèn)證的基本流程如下:

            圖中的(1)~(7)詳細(xì)過程如下:

            (1)Client啟動(dòng)后立即嘗試連接realmlist.wtf文件中指定的認(rèn)證服務(wù)器,就發(fā)送LogonChallenge給認(rèn)證服務(wù)器realmd。協(xié)議結(jié)構(gòu)如下:

               1: typedef struct AUTH_LOGON_CHALLENGE_C
               2: {
               3:     uint8   cmd;                //Cmd is the command/operation code of the packet. Always 0 for this message
               4:     uint8   error;
               5:     uint16  size;            //Size of the remaining part of the message
               6:     uint8   gamename[4];    //4 byte C-String, containing the String "WoW\0"
               7:     uint8   version1;            //Major version number of the client ( 1 for 1.12.1 )
               8:     uint8   version2;            //Minor version number of the client ( 12 for 1.12.1 )
               9:     uint8   version3;            //Patchlevel version number of the client ( 1 for 1.12.1 )
              10:     uint16  build;            //Build number of the client. ( 5875 for 1.12.1 )
              11:     uint8   platform[4];        //Platform the client is running on, reversed C-String ( "68x\0" for x86 )
              12:     uint8   os[4];            //OS the client is running on, reversed C-String ( "niW\0" for Windows )
              13:     uint8   country[4];        //Locale of the client, reversed C-String ( "SUne" for enUS )
              14:     uint32  timezone_bias;
              15:     uint32  ip;                //IP address of the client in binary format
              16:     uint8   I_len;            //Length of the Identity ( user name ) in characters
              17:     uint8   I[1];                //The Identity string ( user name )
              18: } sAuthLogonChallenge_C;

            uint8 I[1]是一個(gè)unsigned char的變長數(shù)組的頭指針,保存user name,服務(wù)器端保存的時(shí)候要把\0后面的東西去掉,防止SQL injection。(1.1)執(zhí)行“SELECT sha_pass_hash,id,locked,last_ip,gmlevel,v,s FROM account WHERE username = '%s'”語句從數(shù)據(jù)庫中讀取數(shù)據(jù)。

            realmd收到sAuthLogonChallenge_C協(xié)議后處理步驟如下:

            1) 檢查該ip是否被封禁,如果是發(fā)送相應(yīng)的錯(cuò)誤

            2) 查詢數(shù)據(jù)庫中是否有該賬戶,如果沒有返回相應(yīng)的錯(cuò)誤

            3) 查看最后一次登錄ip與賬戶是否綁定,如果綁定對比當(dāng)前ip與last_ip是否一致

            4) 檢查該賬號是否被封禁,如果是發(fā)送相應(yīng)的錯(cuò)誤信息

            5) 獲取用戶名密碼,開始SRP6計(jì)算,參見本文最下方的附錄《MaNGOS所使用的SRP6算法》

            6) _accountSecurityLevel,保存用戶的權(quán)限等級,普通用戶、GM、admin等等

            7) 本地化:根據(jù)_localizationName的名字找對應(yīng)的.mpq文件所在的位置比如enUS,zhTW,zhCN

             

            (2) realmd向client發(fā)送challenge,協(xié)議如下:

               1: typedef struct
               2: {
               3:     uint8   cmd;            //Cmd is the command/operation code of the packet. Always 0 for this message.
               4:     uint8   error;
               5:     uint8   unk2;        //random value
               6:     uint8   B[32];        //B is an SRP6 value. It is the server's public value.
               7:     uint8   g_len;        //Length of the SRP6 g value we send the client in bytes. Always 1
               8:     uint8   g[1];            //The SRP6 g value we send the client. Always 7
               9:     uint8   N_len;        //Lenght of the SRP6 N value we send the client. Always 32
              10:     uint8   N[32];        //The SRP6 N value we send the client. 
              11:     uint8   s[32];        //The SRP6 s value
              12:     uint8   unk3[16];        //a randomly generated 16 byte value.
              13:     uint8   unk4;        //a single byte 0.
              14: } sAuthLogonChallenge_S;

             

             

            (3)客戶端的Handshaking階段,client為了回應(yīng)realmd的challenge消息,證明client的密碼和server上保存的密碼一致,需要計(jì)算M1值,并發(fā)送給realmd,發(fā)送的協(xié)議如下:

               1: typedef struct AUTH_LOGON_PROOF_C
               2: {
               3:     uint8   cmd;                    //Cmd is the command/operation code of the packet. Always 1 for this message
               4:     uint8   A[32];                //The client SRP6 A value ( public client value ).
               5:     uint8   M1[20];                //The client's SRP6 M value.待比較的最終值
               6:     uint8   crc_hash[20];            //doesn't seem to be used
               7:     uint8   number_of_keys;        //It also seems to be always 0
               8:     uint8   securityFlags;                 // 0x00-0x04
               9: } sAuthLogonProof_C;

            計(jì)算公式如下,各個(gè)變量的含義請查看本文最下方的附錄《MaNGOS所使用的SRP6算法》

            A = g^a mod N //a為19個(gè)字節(jié)的隨機(jī)數(shù)

            B = (kv + g^b) mod N

            u = H(A, B)

            x = H(s, p)

            S = (B - kg^x) ^ (a + ux)

            K = H(S)

            M = H(H(N) xor H(g), H(I), s, A, B, K)

            上訴的哈希函數(shù)H都使用的是SHA1

             

            (4)realmd收到client發(fā)來的Proof協(xié)議,(a)開始檢查版本是否允許,(b) 使用SRP6計(jì)算M值,與client傳過來的M1做對比,if (!memcmp(M.AsByteArray(), lp.M1, 20)) { } (c) 如果M值相等計(jì)算K —— 即sessionkey,并最終保存到數(shù)據(jù)庫。

             

            (5)驗(yàn)證成功,realmd向client發(fā)送server的logon proof

               1: typedef struct AUTH_LOGON_PROOF_S
               2: {
               3:     uint8   cmd;
               4:     uint8   error;
               5:     uint8   M2[20];            //The SRP6 M values,M = H(H(N) xor H(g), H(I), s, A, B, K)
               6:     uint32  unk1;            // AccountFlags (trial 0x08, ProPass 0x800000, gm 0x01)
               7:     uint32  unk2;            // SurveyId
               8:     uint16  unk3;            // some flags (AccountMsgAvailable = 0x01)
               9: } sAuthLogonProof_S;

             

             

            (6)_HandleRealmList,查詢r(jià)ealmcharacters表獲得角色和realmid的對應(yīng)關(guān)系,然后可以在RealmList類里通過realmid找到對應(yīng)的表項(xiàng),RealmList在初始化的時(shí)候再realmlist表里讀取數(shù)據(jù)放在內(nèi)存里使用:“SELECT id, name, address, port, icon, realmflags, timezone, allowedSecurityLevel, population, realmbuilds FROM realmlist WHERE (realmflags & 1) = 0 ORDER BY name ” 查詢邏輯服務(wù)器。

             

            (7)發(fā)送realmlist給客戶端,客戶端選擇對應(yīng)的服務(wù)器后點(diǎn)擊enter world的時(shí),會(huì)主動(dòng)斷開和realmd的連接。

             

            總結(jié):整個(gè)登錄認(rèn)證過程主要干了如下幾件事

            (a)使用公鑰算法驗(yàn)證client的合法性。

            (b)client合法的情況下,計(jì)算sessionkey并保存在MySQL里,以備后面的邏輯服務(wù)器使用。

            (c)驗(yàn)證通過后,把邏輯服務(wù)器列表發(fā)給client。

            其中最為重要的就是在驗(yàn)證合法性、交換密鑰的過程中,如何在傳遞的協(xié)議里隱藏client的密鑰,使其在被截獲的情況下也無法被黑客解析,這就只能依仗密碼學(xué)了。WOW所使用的加密算法是SRP6,詳細(xì)的介紹如下:

             

             

             

            附錄:MaNGOS所使用的SRP6算法

            SRP全稱Secure Remote Password(安全遠(yuǎn)程密碼).使用SRP的客戶機(jī)和服務(wù)器不會(huì)在網(wǎng)絡(luò)上傳送明文密碼,這樣可以消除直接密碼嗅探行為,另外使用高強(qiáng)度的算法保證了不可能使用字典法攻擊嗅探到的數(shù)據(jù)[1]。SRP協(xié)議的描述見 http://srp.stanford.edu/design.html

            SRP6名詞解釋:

            N - A large safe prime (N = 2q+1, where q is prime) All arithmetic is done modulo N.

            g - A generator modulo N

            k - Multiplier parameter (k = H(N, g) in SRP-6a, k = 3 for legacy SRP-6)

            s - User's salt

            I - Username

            p - Cleartext Password

            H() - One-way hash function

            ^ - (Modular) Exponentiation

            u - Random scrambling parameter

            a,b - Secret ephemeral values

            A,B - Public ephemeral values

            x - Private key (derived from p and s)

            v - Password verifier

            對應(yīng)MaNGOS的計(jì)算方法和變量含義:

            sha_pass_hash:使用這個(gè)函數(shù)進(jìn)行Sha1Hash哈希std::string AccountMgr::CalculateShaPassHash(std::string& name, std::string& password)后得到的值。

            N: A large safe prime (N = 2q+1, where q is prime), All arithmetic is done modulo N. 在MaNGOS里N被設(shè)成N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7");

            s: 32個(gè)字節(jié)的隨機(jī)數(shù),算過一次后保存在數(shù)據(jù)庫里。

            x: 計(jì)算v值使用到的x,即私鑰是s與數(shù)據(jù)庫里的sha_pass_hash的倒置的Sha1Hash

            v: g^x mod N,驗(yàn)證密碼時(shí)使用Password verifier,算過一次后保存在數(shù)據(jù)庫里。

            g: g = 7

            b: 為19個(gè)字節(jié)的隨機(jī)數(shù),每次client連接認(rèn)證的時(shí)候重新生成。

            a: 19個(gè)字節(jié)的隨機(jī)數(shù),由客戶端產(chǎn)生。

            B: 公鑰, gmod = g^b, N , B = ((v * 3) + gmod) % N

            K: 認(rèn)證通過后最終保存到數(shù)據(jù)庫里的sessionkey,(1)計(jì)算A 客戶端公鑰A = g^a mod N a為19為隨機(jī)數(shù),(2)計(jì)算x,x = sha(s, I),I = sha(“username : password”); (3)計(jì)算u,u = sha(A, B) //(服務(wù)公鑰,客戶公鑰);(4)計(jì)算S,S = (B - g^x*3)^(a+u*x); (5)計(jì)算K,S為32位,K為40位是 sha(s奇部分)20位, sha(s偶部分)20位的奇偶交錯(cuò)組合。

            M: 20個(gè)字節(jié)的數(shù),用于與client傳過來的最終結(jié)果M1進(jìn)行對比,如果M和M1每個(gè)字節(jié)都相等則驗(yàn)證通過。計(jì)算方法:t3 = sha(N)[i] ^ sha(g)[i],t4 = sha(username),M = sha(t3,t4,s,A,B,K)

            k: k = 3

            總結(jié):服務(wù)端,客戶端各自計(jì)算S的公式個(gè)不同,公鑰部分服務(wù)端用A,b, 客戶端用B,a 但其計(jì)算結(jié)果相同………私鑰x被很好的隱藏了,因?yàn)橄霃腗獲得x是基本不可能的!基于數(shù)學(xué)難題基礎(chǔ)上的加密算法確實(shí)很給力。

             

            References

            [1]http://blog.csdn.net/lfhfut/article/details/1124768

            [2]http://www.arcemu.org/wiki/

            [3]http://hi.baidu.com/zyy503950958/blog/item/3addce90a91eda81a877a463.html

            777米奇久久最新地址| 久久中文字幕人妻熟av女| 99久久精品午夜一区二区| 国产成人精品久久二区二区| 精品久久久久久无码中文字幕一区 | 亚洲精品乱码久久久久久| 国产情侣久久久久aⅴ免费| 色综合久久中文色婷婷| 中文字幕亚洲综合久久菠萝蜜| 人妻久久久一区二区三区| 久久高清一级毛片| 9久久9久久精品| 99久久国产综合精品女同图片| 99久久国产主播综合精品| 香蕉久久夜色精品升级完成| 精品国产综合区久久久久久| WWW婷婷AV久久久影片| 久久精品人妻中文系列| 久久久久噜噜噜亚洲熟女综合| 热re99久久6国产精品免费| 色综合合久久天天给综看| 免费国产99久久久香蕉| 久久精品夜夜夜夜夜久久| 国产精品中文久久久久久久| 国产精品99久久久久久董美香| 人妻无码αv中文字幕久久琪琪布 人妻无码久久一区二区三区免费 人妻无码中文久久久久专区 | 久久久无码精品亚洲日韩软件| 久久国产亚洲高清观看| 2020国产成人久久精品| 午夜精品久久久久久| 久久国产精品偷99| 丰满少妇人妻久久久久久4| 久久综合狠狠色综合伊人| av午夜福利一片免费看久久| 久久国产精品77777| 久久香综合精品久久伊人| 18岁日韩内射颜射午夜久久成人 | 久久久噜噜噜久久中文字幕色伊伊| 久久青青国产| 综合久久精品色| 久久人妻AV中文字幕|