示例#1
0
        void GenerateSecurity(SecurityFlags flags)
        {
            m_security_flag = FromSecurityFlags(flags);
            m_security_flags = flags;
            m_client_security = true;

            //don't need about solving problem CA2000
            Packet response = new Packet(0x5000);

            response.WriteUInt8(m_security_flag);

            if (m_security_flags.blowfish == 1)
            {
                m_initial_blowfish_key = NextUInt64();

                m_blowfish.Initialize(BitConverter.GetBytes(m_initial_blowfish_key));

                response.WriteUInt64(m_initial_blowfish_key);
            }
            if (m_security_flags.security_bytes == 1)
            {
                m_seed_count = NextUInt8();
                SetupCountByte(m_seed_count);
                m_crc_seed = NextUInt8();

                response.WriteUInt32(m_seed_count);
                response.WriteUInt32(m_crc_seed);
            }
            if (m_security_flags.handshake == 1)
            {
                m_handshake_blowfish_key = NextUInt64();
                m_value_x = NextUInt32() & 0x7FFFFFFF;
                m_value_g = NextUInt32() & 0x7FFFFFFF;
                m_value_p = NextUInt32() & 0x7FFFFFFF;
                m_value_A = G_pow_X_mod_P(m_value_p, m_value_x, m_value_g);

                response.WriteUInt64(m_handshake_blowfish_key);
                response.WriteUInt32(m_value_g);
                response.WriteUInt32(m_value_p);
                response.WriteUInt32(m_value_A);
            }

            m_outgoing_packets.Add(response);
        }
示例#2
0
        void Handshake(ushort packet_opcode, PacketReader packet_data, bool packet_encrypted)
        {
            if (packet_encrypted)
            {
                throw (new Exception("[SecurityAPI::Handshake] Received an illogical (encrypted) handshake packet."));
            }
            if (m_client_security)
            {
                // If this object does not need a handshake
                if (m_security_flags.handshake == 0)
                {
                    // Client should only accept it then
                    if (packet_opcode == 0x9000)
                    {
                        if (m_accepted_handshake)
                        {
                            throw (new Exception("[SecurityAPI::Handshake] Received an illogical handshake packet (duplicate 0x9000)."));
                        }
                        m_accepted_handshake = true; // Otherwise, all good here
                        return;
                    }
                    // Client should not send any 0x5000s!
                    else if (packet_opcode == 0x5000)
                    {
                        throw (new Exception("[SecurityAPI::Handshake] Received an illogical handshake packet (0x5000 with no handshake)."));
                    }
                    // Programmer made a mistake in calling this function
                    else
                    {
                        throw (new Exception("[SecurityAPI::Handshake] Received an illogical handshake packet (programmer error)."));
                    }
                }
                else
                {
                    // Client accepts the handshake
                    if (packet_opcode == 0x9000)
                    {
                        // Can't accept it before it's started!
                        if (!m_started_handshake)
                        {
                            throw (new Exception("[SecurityAPI::Handshake] Received an illogical handshake packet (out of order 0x9000)."));
                        }
                        if (m_accepted_handshake) // Client error
                        {
                            throw (new Exception("[SecurityAPI::Handshake] Received an illogical handshake packet (duplicate 0x9000)."));
                        }
                        // Otherwise, all good here
                        m_accepted_handshake = true;
                        return;
                    }
                    // Client sends a handshake response
                    else if (packet_opcode == 0x5000)
                    {
                        if (m_started_handshake) // Client error
                        {
                            throw (new Exception("[SecurityAPI::Handshake] Received an illogical handshake packet (duplicate 0x5000)."));
                        }
                        m_started_handshake = true;
                    }
                    // Programmer made a mistake in calling this function
                    else
                    {
                        throw (new Exception("[SecurityAPI::Handshake] Received an illogical handshake packet (programmer error)."));
                    }
                }

                ulong key_array = 0;
                byte[] tmp_bytes;

                m_value_B = packet_data.ReadUInt32();
                m_client_key = packet_data.ReadUInt64();

                m_value_K = G_pow_X_mod_P(m_value_p, m_value_x, m_value_B);

                key_array = MAKELONGLONG_(m_value_A, m_value_B);
                KeyTransformValue(ref key_array, m_value_K, (byte)(LOBYTE_(LOWORD_(m_value_K)) & 0x03));
                m_blowfish.Initialize(BitConverter.GetBytes(key_array));

                tmp_bytes = m_blowfish.Decode(BitConverter.GetBytes(m_client_key));
                m_client_key = BitConverter.ToUInt64(tmp_bytes, 0);

                key_array = MAKELONGLONG_(m_value_B, m_value_A);
                KeyTransformValue(ref key_array, m_value_K, (byte)(LOBYTE_(LOWORD_(m_value_B)) & 0x07));
                if (m_client_key != key_array)
                {
                    throw (new Exception("[SecurityAPI::Handshake] Client signature error."));
                }

                key_array = MAKELONGLONG_(m_value_A, m_value_B);
                KeyTransformValue(ref key_array, m_value_K, (byte)(LOBYTE_(LOWORD_(m_value_K)) & 0x03));
                m_blowfish.Initialize(BitConverter.GetBytes(key_array));

                m_challenge_key = MAKELONGLONG_(m_value_A, m_value_B);
                KeyTransformValue(ref m_challenge_key, m_value_K, (byte)(LOBYTE_(LOWORD_(m_value_A)) & 0x07));
                tmp_bytes = m_blowfish.Encode(BitConverter.GetBytes(m_challenge_key));
                m_challenge_key = BitConverter.ToUInt64(tmp_bytes, 0);

                KeyTransformValue(ref m_handshake_blowfish_key, m_value_K, 0x3);
                m_blowfish.Initialize(BitConverter.GetBytes(m_handshake_blowfish_key));

                SecurityFlags tmp_flags = new SecurityFlags();
                tmp_flags.handshake_response = 1;
                byte tmp_flag = FromSecurityFlags(tmp_flags);

                //CA2000 dont care
                Packet response = new Packet(0x5000);
                response.WriteUInt8(tmp_flag);
                response.WriteUInt64(m_challenge_key);
                m_outgoing_packets.Add(response);
            }
            else
            {
                if (packet_opcode != 0x5000)
                {
                    throw (new Exception("[SecurityAPI::Handshake] Received an illogical handshake packet (programmer error)."));
                }

                byte flag = packet_data.ReadByte();

                SecurityFlags flags = ToSecurityFlags(flag);

                if (m_security_flag == 0)
                {
                    m_security_flag = flag;
                    m_security_flags = flags;
                }

                if (flags.blowfish == 1)
                {
                    m_initial_blowfish_key = packet_data.ReadUInt64();
                    m_blowfish.Initialize(BitConverter.GetBytes(m_initial_blowfish_key));
                }

                if (flags.security_bytes == 1)
                {
                    m_seed_count = packet_data.ReadUInt32();
                    m_crc_seed = packet_data.ReadUInt32();
                    SetupCountByte(m_seed_count);
                }

                if (flags.handshake == 1)
                {
                    m_handshake_blowfish_key = packet_data.ReadUInt64();
                    m_value_g = packet_data.ReadUInt32();
                    m_value_p = packet_data.ReadUInt32();
                    m_value_A = packet_data.ReadUInt32();

                    m_value_x = NextUInt32() & 0x7FFFFFFF;

                    m_value_B = G_pow_X_mod_P(m_value_p, m_value_x, m_value_g);
                    m_value_K = G_pow_X_mod_P(m_value_p, m_value_x, m_value_A);

                    ulong key_array = MAKELONGLONG_(m_value_A, m_value_B);
                    KeyTransformValue(ref key_array, m_value_K, (byte)(LOBYTE_(LOWORD_(m_value_K)) & 0x03));
                    m_blowfish.Initialize(BitConverter.GetBytes(key_array));

                    m_client_key = MAKELONGLONG_(m_value_B, m_value_A);
                    KeyTransformValue(ref m_client_key, m_value_K, (byte)(LOBYTE_(LOWORD_(m_value_B)) & 0x07));
                    byte[] tmp_bytes = m_blowfish.Encode(BitConverter.GetBytes(m_client_key));
                    m_client_key = BitConverter.ToUInt64(tmp_bytes, 0);
                }

                if (flags.handshake_response == 1)
                {
                    m_challenge_key = packet_data.ReadUInt64();

                    ulong expected_challenge_key = MAKELONGLONG_(m_value_A, m_value_B);
                    KeyTransformValue(ref expected_challenge_key, m_value_K, (byte)(LOBYTE_(LOWORD_(m_value_A)) & 0x07));
                    byte[] tmp_bytes = m_blowfish.Encode(BitConverter.GetBytes(expected_challenge_key));
                    expected_challenge_key = BitConverter.ToUInt64(tmp_bytes, 0);

                    if (m_challenge_key != expected_challenge_key)
                    {
                        throw (new Exception("[SecurityAPI::Handshake] Server signature error."));
                    }

                    KeyTransformValue(ref m_handshake_blowfish_key, m_value_K, 0x3);
                    m_blowfish.Initialize(BitConverter.GetBytes(m_handshake_blowfish_key));
                }

                // Generate the outgoing packet now
                if (flags.handshake == 1 && flags.handshake_response == 0)
                {
                    // Check to see if we already started a handshake
                    if (m_started_handshake || m_accepted_handshake)
                    {
                        throw (new Exception("[SecurityAPI::Handshake] Received an illogical handshake packet (duplicate 0x5000)."));
                    }

                    // Handshake challenge
                    //CA2000 dont care
                    Packet response = new Packet(0x5000);
                    response.WriteUInt32(m_value_B);
                    response.WriteUInt64(m_client_key);
                    m_outgoing_packets.Insert(0, response);

                    // The handshake has started
                    m_started_handshake = true;
                }
                else
                {
                    // Check to see if we already accepted a handshake
                    if (m_accepted_handshake)
                    {
                        throw (new Exception("[SecurityAPI::Handshake] Received an illogical handshake packet (duplicate 0x5000)."));
                    }

                    // Handshake accepted
                    //CA2000 dont care
                    Packet response1 = new Packet(0x9000);

                    // Identify
                    //CA2000 dont care
                    Packet response2 = new Packet(0x2001, true, false);
                    response2.WriteAscii(m_identity_name);
                    response2.WriteUInt8(m_identity_flag);

                    // Insert at the front, we want 0x9000 first, then 0x2001
                    m_outgoing_packets.Insert(0, response2);
                    m_outgoing_packets.Insert(0, response1);

                    // Mark the handshake as accepted now
                    m_started_handshake = true;
                    m_accepted_handshake = true;
                }
            }
        }