• <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>

            牽著老婆滿街逛

            嚴以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            Wow, Mangos登錄時的SRP6認證

            轉載自:http://blog.csdn.net/jq0123/archive/2009/04/10/4062020.aspx

            以Mangos代碼為參考, 解析SRP6的原理和實現.
            (轉載請注明來源于金慶的專欄)

            SRP全稱Secure Remote Password(安全遠程密碼),是一個開源認證協議。

            SRP簡化后的原理是:
            1. 服務器不保存密碼或密碼的散列值, 防止字典攻擊. 
               而只是保存驗證因子(verifier).
            2. 客戶端和服務器可以各自計算出一個會話秘鑰(session key), 其值相同. 防止竊聽.


            參考:
            Wow 服務器解析 ( http://www.shnenglu.com/Jedimaster/archive/2006/10/14/13674.aspx )
            SRP Protocol Design ( http://srp.stanford.edu/design.html )
            魔獸世界服務器端編寫參考資料 ( http://www.asstudio.de/wow/wow.htm )
            RFC2954中文翻譯 ( http://www.cnpaf.net/rfc/rfc2945.txt )
            SRP是什么意思?_百度知道 ( http://zhidao.baidu.com/question/59783252.html )
            源碼 mangos/src/realmd/AuthSocket.cpp

            == Mangos SRP6認證過程 ==

             

            1. 客戶端發送用戶名和版本信息

                struct AUTH_LOGON_CHALLENGE_C
                
            {
                    uint8   cmd;
                    uint8   error;
                    uint16  size;
                    uint8   gamename[
            4];
                    uint8   version1;
                    uint8   version2;
                    uint8   version3;
                    uint16  build;
                    uint8   platform[
            4];
                    uint8   os[
            4];
                    uint8   country[
            4];
                    uint32  timezone_bias;
                    uint32  ip;
                    uint8   I_len;
                    uint8   I[
            1];
                }
            ;




            大部份信息用來決定是否封阻該用戶登錄.
            SRP6相關的只有I, 為用戶名. 
            SRP6相關的字段都是按協議中的符號定義的.


            1.1 _SetVSFields(rI)設置v, s字段

            從數據庫中獲取密碼散列值rI(字段名sha_pass_hash), 應該是密碼p, 
            x = H(s, p)
            v = g^x (密碼學中的計算一般都是在最后對大質數N取模: v = g.ModExp(x, N);)
            這個應該是驗證因子v.
            然后v, s存入數據庫. x為臨時值, 用后丟棄.

            salt值s是在連接時設置的隨機值.

            /// Accept the connection and set the s random value for SRP6
            void AuthSocket::OnAccept()
            {
                s.SetRand(s_BYTE_SIZE 
            * 8);
            }

            s是32字節長, s_BYTE_SIZE = 32.

            安全大質數N, 及其生成元g, 是固定的:
                N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7");
                g.SetDword(7);

            RFC2945:
               For
               maximum security, N should be a safe prime (i.e. a number of the form
               N = 2q + 1, where q is also prime).  Also, g should be a generator
               modulo N (see [SRP] for details), which means that for any X where 0
               < X < N, there exists a value x for which g^x % N == X.

            為了最大化安全性,N可以是一個安全的素數
            (也就是,一個類似于N=2q + 1形式的數,同時q是個素數)。
            而且,g將是一個以N為模的生成元,
            意味著,對任何X,有0 < X < N,存在一個值x,使得g^x % N == X。

            Mangos保存了密碼p, 是錯誤的. 服務器不應該保存密碼或其散列值.
            應該在創建用戶時, 由客戶端取s值, 計算v, 將{I, s, v}傳輸到服務器并保存.
            登錄時, 特定用戶的s, v應該是固定的, 從數據庫讀取, 而不是每次登錄時隨機.

            1.2 取b值, 計算B

                b.SetRand(19 * 8);
                BigNumber gmod
            =g.ModExp(b, N);
                B 
            = ((v * 3+ gmod) % N;

            b為19字節長的隨機數. 不知為何是19字節長, 不是16或32? 
            b是服務器的臨時秘鑰, B為臨時公鑰.
            B = kv + g^b
            在SRP6中k=3, 而在最新的SRP6a中, k=H(N, g).

            1.3 服務端返回 CMD_AUTH_LOGON_CHALLENGE 數據包

            返回的數據結構沒有用struct定義, 只是用ByteBuffer依次填入數據.

                ByteBuffer pkt;
                
                pkt 
            << (uint8) AUTH_LOGON_CHALLENGE;
                pkt 
            << (uint8) 0x00;
                pkt 
            << (uint8)REALM_AUTH_SUCCESS;
                pkt.append(B.AsByteArray(
            32), 32);   // 32 bytes
                pkt << (uint8)1;
                pkt.append(g.AsByteArray(), 
            1);
                pkt 
            << (uint8)32;
                pkt.append(N.AsByteArray(), 
            32);
                pkt.append(s.AsByteArray(), s.GetNumBytes());   
            // 32 bytes
                pkt.append(unk3.AsByteArray(), 16);
                pkt 
            << (uint8)0;                    // Added in 1.12.x client branch
                
                SendBuf((
            char const*)pkt.contents(), pkt.size());



            B, g, N, s 是服務器發給客戶端的SRP6參數.
            unk3是個16字節長的隨機數, 不知道干什么用的. (unknown3?)

            按SRP6的協議, 應該是客戶端先發送自己的用戶名和公鑰(I, A), 但在Mangos中,
            是服務器在沒有收到A時就發送鹽值和自己的公鑰(s, B).
            這個次序應該無關緊要. 這樣做的原因是服務器要先發送N, g到客戶端, 這樣可少一次消息交互.
            客戶端計算公鑰A時要用到N, g: A = g^a (隱含對N取模).

            2. 客戶端發送 CMD_AUTH_LOGON_PROOF 數據包請求驗證

                struct AUTH_LOGON_PROOF_C
                
            {
                    uint8   cmd;
                    uint8   A[
            32];
                    uint8   M1[
            20];
                    uint8   crc_hash[
            20];
                    uint8   number_of_keys;
                    uint8   unk;  
            // Added in 1.12.x client branch
                }
            ;



            A, M1有用

            2.1 計算u, S, K

                u = sha(A, B);
                S = (A * (v.ModExp(u, N))).ModExp(b, N);
                K = H(S);
            其中K分奇偶位分別計算, 應該不是SRP的方法, 不知是否會降低散列效果.

            2.2 計算M并與M1比較驗證

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

            2.3 M1驗證通過后計算M2, 用于客戶端驗證

                M2 = sha(A, M, K)

            2.4 服務端發回 CMD_AUTH_LOGON_PROOF

            包含了 SRP6 驗證的結果 M2 

                struct AUTH_LOGON_PROOF_S
                
            {                        
                    uint8   cmd;         
                    uint8   error;       
                    uint8   M2[
            20];      
                    uint32  unk1;        
                    uint32  unk2;        
                    uint16  unk3;        
                }
            ;

             

            posted on 2010-02-26 16:30 楊粼波 閱讀(1610) 評論(1)  編輯 收藏 引用

            評論

            # re: Wow, Mangos登錄時的SRP6認證 2012-04-05 22:44 iicup

            如果是驗證密碼,服務器必須要有密碼的某種形式的散列值吧.
            比如所謂的驗證因子也應該是散列值的一種.
            另外, 服務器先發鹽值,可以讓客戶端接收到信息后立刻發送信息到服務器驗證,
            然后立刻可以刪除密碼.
            這樣可以最大程度減小密碼在客戶端內存的保留時間,有利于安全.  回復  更多評論   

            亚洲国产精品久久久久婷婷软件| 中文无码久久精品| 精品无码久久久久久午夜| 一本色道久久88综合日韩精品 | 久久精品视频91| 国产A级毛片久久久精品毛片| 久久AV高清无码| 久久综合狠狠综合久久综合88| 久久久久久久久久久| 精品国产乱码久久久久软件| 久久人人爽人人爽人人片AV东京热 | 亚洲欧美日韩中文久久| 国内精品久久国产| 99久久精品国产一区二区| 18禁黄久久久AAA片| 久久精品日日躁夜夜躁欧美| 国产A三级久久精品| 亚洲精品无码久久久久sm| 97久久精品人妻人人搡人人玩| 久久精品国产精品亚洲精品| 国产午夜久久影院| 久久综合视频网站| 久久人人爽爽爽人久久久| 99久久精品国产麻豆| 久久99精品国产麻豆蜜芽| 久久这里只精品99re66| 精品久久久久久无码专区| 精品国产乱码久久久久久浪潮| 午夜精品久久久久9999高清| 囯产极品美女高潮无套久久久| 久久婷婷五月综合97色| 久久久久国产精品麻豆AR影院| 精品国产青草久久久久福利| 国产精品久久久久久久久| 无夜精品久久久久久| 国内精品人妻无码久久久影院| 久久一区二区三区99| 久久久久人妻精品一区二区三区| 久久精品中文字幕第23页| 久久久久亚洲精品无码蜜桃| 日本加勒比久久精品|