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 PHPMysql_
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....