コード例 #1
0
        public static bool SignOnlineUserSignature(ref ONLINE_USER_ACCOUNT_STRUCT Account)
        {
            byte[] account = Account.Serialize(); //struct to byte array, prefer serialization over C#'s 'unsafe' functionality even if slightly slower

            byte[] seed_data  = { 0xA7, 0x14, 0x21, 0x3D, 0x94, 0x46, 0x1E, 0x05, 0x97, 0x6D, 0xE8, 0x35, 0x21, 0x2A, 0xE5, 0x7C };
            byte[] seed_key_a = { 0x2B, 0xB8, 0xD9, 0xEF, 0xD2, 0x04, 0x6D, 0x9D, 0x1F, 0x39, 0xB1, 0x5B, 0x46, 0x58, 0x01, 0xD7 };
            byte[] seed_key_b = { 0x1E, 0x05, 0xD7, 0x3A, 0xA4, 0x20, 0x6A, 0x7B, 0xA0, 0x5B, 0xCD, 0xDF, 0xAD, 0x26, 0xD3, 0xDE };
            byte[] auth_key   = { 0x62, 0xBD, 0x92, 0xB6, 0x4F, 0x45, 0x84, 0x70, 0xD3, 0xFF, 0x4F, 0x22, 0x3C, 0x6E, 0xE7, 0xEA };
            byte[] IV         = { 0x7B, 0x35, 0xA8, 0xB7, 0x27, 0xED, 0x43, 0x7A };

            //generate tripledes key (3DES)
            //NOTE: for a "machine signed" account, replace seed_data with XboxHDKey (machine signed will make the account 'non-roamable')
            byte[] tempHash;
            byte[] Key = new byte[0x18];

            //store first 4 bytes of resulting hash
            Kernel.XCryptHMAC(seed_key_a, seed_data, 0, 0x10, out tempHash);
            Array.Copy(tempHash, 0, Key, 0, 4);

            //store entire hash result, beginning from 0x4 in the key
            Kernel.XCryptHMAC(seed_key_b, seed_data, 0, 0x10, out tempHash);
            Array.Copy(tempHash, 0, Key, 0x4, 0x14);

            /*
             * possible to use pre-computed key if not 'machine signing' to save on cpu cycles
             * 0x2B, 0x84, 0x95, 0xE8, 0x82, 0xE2, 0xA3, 0x33, 0x30, 0x60, 0x6D, 0x8A, 0xDA, 0x8B, 0x26, 0x93, 0x4E, 0x3A, 0x9D, 0xF6, 0xF5, 0xB8, 0xFA
             *
             *
             * below is the resulting 3DES key layout // Ax = seed_key_a hash result bytes // Bx = seed_key_b hash result bytes
             * 0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  19  20  21  22  23  24  // INDEX
             * A0  A1  A2  A3 B0 B1 B2 B3 B4 B5  B6  B7  B8  B9  B10 B11 B12 B13 B14 B15 B16 B17 B18 // 3DES KEY LAYOUT
             */

            //compute hash of first 0x64 (100) bytes of account data using auth_key, covering all account variables and the confounder
            //NOTE: for a "machine signed" account, replace auth_key with XboxHDKey
            byte[] auth_hash;
            Kernel.XCryptHMAC(auth_key, account, 0, 0x64, out auth_hash);

            //encrypt the first 0x10 bytes of confounder (confounder is 0x14 bytes total) in the account data
            if (Kernel.XCryptBlockCryptCBC(Key, IV, ref account, 0x50, 0x10, true))
            {
                //store first 8 bytes of the resulting hash computed over the account data and decrypted confounder, used for authenticating the account
                Array.Copy(auth_hash, 0, account, 0x64, 8);

                //move working buffer back into struct
                Account = account.Deserialize <ONLINE_USER_ACCOUNT_STRUCT>();

                return(true);
            }

            return(false);
        }
コード例 #2
0
        public static bool VerifyOnlineUserSignature(ONLINE_USER_ACCOUNT_STRUCT Account)
        {
            byte[] account = Account.Serialize(); //struct to byte array, prefer serialization over C#'s 'unsafe' functionality even if slightly slower

            byte[] seed_data  = { 0xA7, 0x14, 0x21, 0x3D, 0x94, 0x46, 0x1E, 0x05, 0x97, 0x6D, 0xE8, 0x35, 0x21, 0x2A, 0xE5, 0x7C };
            byte[] seed_key_a = { 0x2B, 0xB8, 0xD9, 0xEF, 0xD2, 0x04, 0x6D, 0x9D, 0x1F, 0x39, 0xB1, 0x5B, 0x46, 0x58, 0x01, 0xD7 };
            byte[] seed_key_b = { 0x1E, 0x05, 0xD7, 0x3A, 0xA4, 0x20, 0x6A, 0x7B, 0xA0, 0x5B, 0xCD, 0xDF, 0xAD, 0x26, 0xD3, 0xDE };
            byte[] auth_key   = { 0x62, 0xBD, 0x92, 0xB6, 0x4F, 0x45, 0x84, 0x70, 0xD3, 0xFF, 0x4F, 0x22, 0x3C, 0x6E, 0xE7, 0xEA };
            byte[] IV         = { 0x7B, 0x35, 0xA8, 0xB7, 0x27, 0xED, 0x43, 0x7A };

            //generate tripledes key (3DES)
            //NOTE: for a "machine signed" account, replace seed_data with XboxHDKey (machine signed will make the account 'non-roamable')
            byte[] tempHash;
            byte[] Key = new byte[0x18];

            //store first 4 bytes of resulting hash
            Kernel.XCryptHMAC(seed_key_a, seed_data, 0, 0x10, out tempHash);
            Array.Copy(tempHash, 0, Key, 0, 4);

            //store entire hash result, beginning from 0x4 in the key
            Kernel.XCryptHMAC(seed_key_b, seed_data, 0, 0x10, out tempHash);
            Array.Copy(tempHash, 0, Key, 0x4, 0x14);

            /*
             * possible to use pre-computed key if not 'machine signing' to save on cpu cycles
             * 0x2B, 0x84, 0x95, 0xE8, 0x82, 0xE2, 0xA3, 0x33, 0x30, 0x60, 0x6D, 0x8A, 0xDA, 0x8B, 0x26, 0x93, 0x4E, 0x3A, 0x9D, 0xF6, 0xF5, 0xB8, 0xFA
             *
             *
             * below is the resulting 3DES key layout // Ax = seed_key_a hash result bytes // Bx = seed_key_b hash result bytes
             * 0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  19  20  21  22  23  24  // INDEX
             * A0  A1  A2  A3 B0 B1 B2 B3 B4 B5  B6  B7  B8  B9  B10 B11 B12 B13 B14 B15 B16 B17 B18 // 3DES KEY LAYOUT
             */

            //decrypt the first 0x10 bytes of confounder (confounder is 0x14 bytes total) in the account data
            if (Kernel.XCryptBlockCryptCBC(Key, IV, ref account, 0x50, 0x10, false))
            {
                //compute hash of first 0x64 (100) bytes of account data using auth_key, covering all account variables and the confounder
                //NOTE: for a "machine signed" account, replace auth_key with XboxHDKey
                byte[] auth_hash;
                Kernel.XCryptHMAC(auth_key, account, 0, 0x64, out auth_hash);

                //compare first 8 bytes of the resulting auth_hash to the 8 stored bytes of the validation bytes (aka the 8 bytes of the last auth_hash)
                if (memcmp(auth_hash, 0, account, 0x64, 8))
                {
                    //other validation checks, these checks are done by the XOnline API and must comply to be considered valid account data

                    //check flags, last 4 bits are resevered and must be zero
                    if ((account[0x1F] & 0xF) == 0)
                    {
                        //check unknown int value stored at 0x8, must be zero (reserved for PARTNER.NET accounts?)
                        if (BitConverter.ToUInt32(account, 8) == 0)
                        {
                            //check gamertag for overflow and is null-terminated
                            if (account[0x1B] == 0)
                            {
                                //check domain for overflow and is null-terminated
                                if (account[0x37] == 0)
                                {
                                    //check realm for overflow and is null-terminated
                                    if (account[0x4F] == 0)
                                    {
                                        return(true); //valid account
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return(false);
        }