TL;DR

I am working on a gaming system that uses UnityScript and C# on the client and PHP on the server. A MD5 hash of the data plus a shared secret is used to check that the data has not been modified in transit. Is MD5 good enough for this? What other hash algorithm could I use that works in all three languages?

The Problem In More Detail

I have come across some code on a widely used community website about the popular Game Development Platform Unity, and I am now working on improving the MySQL, PHP and security of that code.

The code uses a "secret key" value that is shared between the client and the server. All messages from the client includes a hash of the data (e.g. name and score) plus the secret key, that the server checks before accepting the data. This is basically an authentication that the data passed has not been tampered with.

However, because it's MD5 I think someone who is listening to the network traffic could easily work out the secret key and then post whatever data they want to the server. 

So my questions are:


Does this current state of affairs warrent improvement? Or is this the intended current use of MD5 (as of January 2017)?
Is there another hashing algorithm that could further improve/authenticate this communication activity? Please note that the algorithm would need to work in PHP, UnityScript and C#.


The Code


In UnityScript (client side):

var hash=Md5.Md5Sum(name + score + secretKey);

In C# (client side):

string hash = MD5Test.Md5Sum(name + score + secretKey);

In PHP (server side): 

$secretKey = "mySecretKey"; // Change this value to match the value 
                            //stored in the client javascript below 

$realHash = md5($_GET['name'] . $_GET['score'] . $secretKey); 
if($realHash == $hash) {
       //interact with database 
}



Further Criteria


Some Unity programmers use UnityScript (a Python-like language with a JavaScript-like syntax on the .NET API) but no library can be assumed to be installed.
Game Developers are not PHP / MySQL programmers so complex or 3rd party PHP/C#/Js code would probably not be helpful. 
BCrypt is apparently unwise to use with C# 
BCrypt needs a static salt in this instance (perhaps derived from the secret key?) but is intended to work with a random salt. 
PBKDF2 seems to be prefered over BCrypt but can be very slow particularly on mobile devices without much memory. 
Dealing with a secured server can not be expected (if only...). 
I don't know enough about the C# security library to really pick out best options from those listed. 
While the code outlined is simply to do with highscore updates, this code has been in the past - and will be in the future - taken and used for transporting all sorts of data, public and private to various databases.
Dealing with hash algorithm interoperability between PHP, UnityScript, C# is a bigger hurdle than I had anticipated. If it was just PHP I'd use password_hash.



  Some Thoughts and background to this question:
  
  I updated the title as the edited title seemed to suggest that I wasn't sure about changing MD5, whereas knowing I should change MD5 was one of the core reasons of asking the question here in the first place.
  
  The original question was that I wanted to update the terrible code suggestions given on (amongst other places) here about how to handle interactions between a game on a client machine and data storage on a remote server. Bare in mind this is code suggestions for beginner programmers in Unity and this site is [now] run by Unity Technologies themselves.
  If you look, the original question (linked above) was using PHP Mysql_ functions (as well as a rather crappy invalid form of PDO). I felt this would benefit from a rewrite. I saw that the original code had also used an md5 routine to hash the intended data. When it came to the replacement of MD5, I hadn't realised either the vulnerability of compiled project files or the size/scale of the work needed to make this codeblock be actually more secure (on either the interaction with the server or the client side data). 
  My original quest was to find a suitable drop in replacement for the MD5 which could work in the varous languages required (UnityScript, C#, PHP) , as I was aware of it's shortfalls. I hadn't realised (judging by the comments here) how tediously easy it actually is to break into exe's and grab hardcoded data.
  
  This question is NOT about a game I'm making, it is not about My project and the code quoted that I am intending to replace was not written by me. I read a lot of the comments that somehow people are having a go at the messenger, but this question came from my own wish to improve an existing shortcoming on a teaching wiki website. 
  I do have the greatest respect for the knowledge shared in answering this question but I am aware that from the last 6 months exploring the Unity documentation and learning sites that there is a significant gap in securing both local applications and multiplayer or other remote interactions.
  
  I see a lot of responders in comments stating that the answer given by George is a bad answer - but it answers the specific question I asked, at the time. 
  Thanks.   


Final Note:
This Blob post from comments by Luke Briggs underlined how much of an eye openingly easy process it is to manipulate local Unity Game Application data. I did not at all comprehend how vulnerable local files are....

This approach is fundamentally flawed. Anything on the client side can and will be tampered with by players. It is the same problem which makes DRM untenable - the user owns the machine and all the data on it, including your executables, data in memory, etc. Keeping algorithms secret doesn't work (see Kerckhoffs's principle) because it only takes a small amount of reverse engineering work to work out what your code is doing.

For example, let's say you've got a routine in your game client which posts the level score up to the server, using some cryptography of whatever form to ensure that it isn't tampered with over the network. There are a whole bunch of ways to get around this:


Use a memory editing tool such as Cheat Engine to scan for the current score (pause, search the score, unpause, wait for score to change, search again, repeat until you find the memory address which contains the value) and edit it. When the level completes the score value will be happily treated as legitimate by your code, and uploaded to the server.
Modify the game executable on disk so that your "level complete" code ignores the real score value and picks a different one.
Modify the game executable on disk so that simple things (e.g. killing one monster) increases your score by 1000x more than it should do.
Modify the game executable on disk so that you can never die, or have infinite powerups, or one-hit kills, or any other number of helping things, so that you can easily attain a very high score.
Perform any of those modifications in-memory after the game loads so that the original executable stays intact (useful for cases where there are annoying integrity checks)
Simply expose the "we finished a level, now upload the score" code externally from the process so that it can be called by anyone's program. In native code you can inject a small stub and add an entry to the export table, or just directly copy the code into your own executable. In .NET it's trivial to just modify the class and method's visibility flags and import it into a new program. Now you can submit whatever score values you like without ever even running the game.
Reverse engineer the game and get hold of the "secret" key and write your own app to send the score value to the server.


This is just the tip of the iceberg. For more complex games there are all sorts of workarounds to anti-cheat and other problems, but regardless of the defense tricks used there will always be a way to mess with client-side values.

The critical feature of a secure approach is that nothing on the player's computer should be trusted. When your server code receives a packet from a player, assume that your game might not even be running - it could be a totally homebrew piece of code that lies about everything.

Securing multiplayer games (or any kind of game where verifying game state is a requirement) isn't easy. The problem isn't really even a security one, it's a usability and performance one. The simplest way to secure a multiplayer game is to keep the entire game state on the server side, have all the game logic executed and maintained there, and have the client do nothing but send player input over to the server ("user clicked the mouse, user is holding W key") and present the audio and video back to the player. The problem with doing this is that it doesn't make for a very fun game due to network latency, and it's quite hard to scale on the server side. Instead, you have to find a balance between keeping things client-side and server-side. For example, the logic for "does the player have a key to open this door?" must be checked server side, but the logic of when to show the context icon for "open door" stays on the client side. Again, things like enemy health and position must be kept on the server side, and the player's ability to deal damage to that enemy must also be verified (is it near enough?) which means that AI can't be kept client-side, but things like the choice of which idle animation the enemy is displaying will probably be a client-side thing.

We have a few questions on here about game security, so I suggest reading through those:


Preventing artificial latency or "Lag Hacking" in multiplayer games
Secure Software: How to ensure caller is authentic?
Securely sending packets without them being spoofed
Checking a locally stored string for tamper


I also recommend these questions over at GameDev SE:


How can a web game store points online without giving the user the possibility to do the same call but with more points? (almost literally your question)
What are some ways to prevent or reduce cheating in online multiplayer games?
How should multiplayer games handle authentication?


There's also a great paper on multiplayer security from BlackHat EU 2013, and an article on non-authoritative P2P networking, which may both be of use.
