Как рассчитать Хеш сумму файла по средствам C#?
1. Вы можете придумать любую формулу хеша. Идея простая - зафиксировать состояние файла. Этого можно добиться различными стандартными хеш-функциями (есть в оф. примерах), контрольными суммами (тоже есть в оф. примерах). Вы можете подсчитать длину файла, количество 1 в файле, сохранить первые 1000 байт файла. В общем, формулы могут быть любыми.
2. Затем вам надо сохранить хеш. Ваш друг ломает хеш, а вы хешируете хеш. Затем ваш друг ломает хеш хеша и т. д.
3. Поэтому, если вы хотите защититься от дурга, храните хеш на сервере, а перед каждым запуском скачивайте его и проверяйте файл.
4. Но ваш друг поставит прокси и  подменит серверный трафик. Поэтому вам необходимо как-то удостовериться, что хеш получен из надёжного источника. Вы покупаете сертификат и шифруете соединение до сервера.
5. Ну а дальше ваш друг уже начнёт реверс-инженеринг (дизассемблер). И тут вы никак не сможете защититься.
Как вариант забей на проверку хешей файлов. Это такое себе. Лучше шифровать информацию в файле игры.
Смысл в чем? Если игру он не будет разбирать, то ты просто создаешь любой свой "строковый ключ" для шифрования. При выходе из игры, ты значение с "монетами" шифруешь и записываешь в файл. Если он захочет отредактировать, то ему придется помучиться в подборке алгоритма шифрования и дешифрования. Я тебе дал готовое решения для шифрования/дешифрования, только подставь свой ключ. Как вариант сгенерируй ключ через какой нибудь sha1 алгоритм. 
P.S. Откажись от шифрования используя MD5. Он намного медленее SHA1 и менее надежнееpublic static string keyStr = "ТУТ ЛЮБАЯ ТВОЯ СТРОЧКА(Любой рандомный текст)";
  
        public static string Encrypt(string PlainText)
        {
            RijndaelManaged aes = new RijndaelManaged();
            aes.BlockSize = 128;
            aes.KeySize = 256;
            aes.Mode = CipherMode.ECB;

            byte[] keyArr = Convert.FromBase64String(keyStr);
            byte[] KeyArrBytes32Value = new byte[32];
            Array.Copy(keyArr, KeyArrBytes32Value, 32);

            aes.Key = KeyArrBytes32Value;

            ICryptoTransform encrypto = aes.CreateEncryptor();

            byte[] plainTextByte = ASCIIEncoding.UTF8.GetBytes(PlainText);
            byte[] CipherText = encrypto.TransformFinalBlock(plainTextByte, 0, plainTextByte.Length);
            return Convert.ToBase64String(CipherText);
        }
        public static string Decrypt(string CipherText)
        {
            RijndaelManaged aes = new RijndaelManaged();
            aes.BlockSize = 128;
            aes.KeySize = 256;
            aes.Mode = CipherMode.ECB;

            byte[] keyArr = Convert.FromBase64String(keyStr);
            byte[] KeyArrBytes32Value = new byte[32];
            Array.Copy(keyArr, KeyArrBytes32Value, 32);

            aes.Key = KeyArrBytes32Value;

            ICryptoTransform decrypto = aes.CreateDecryptor();

            byte[] encryptedBytes = Convert.FromBase64CharArray(CipherText.ToCharArray(), 0, CipherText.Length);
            byte[] decryptedData = decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
            return ASCIIEncoding.UTF8.GetString(decryptedData);
        }