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); }
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; } } }