Vous ne pouvez pas empêcher l'utilisateur de modifier le fichier. C'est son ordinateur, il peut donc faire ce qu'il veut (c'est pourquoi toute la question des DRM est difficile).
Puisque vous avez dit que vous utilisiez le fichier pour sauvegarder un high-score, vous avez plusieurs possibilités. Notez que, comme nous l'avons dit précédemment, aucune méthode n'empêchera un attaquant vraiment déterminé d'altérer la valeur : puisque votre application est exécutée sur l'ordinateur de l'utilisateur, il peut simplement la décompiler, examiner comment vous protégez la valeur (en accédant à tout secret utilisé dans le processus) et agir en conséquence. Mais si vous êtes prêt à décompiler une application, à découvrir le schéma de protection utilisé et à concevoir un script/patch pour le contourner uniquement pour changer un nombre que vous seul pouvez voir, eh bien, allez-y ?
Obfusquer le contenu
Cela empêchera l'utilisateur de modifier directement le fichier, mais ne l'arrêtera pas dès que l'algorithme d'obfuscation sera connu.
var plaintext = Encoding.UTF8.GetBytes("Hello, world.");
var encodedtext = Convert.ToBase64String(plaintext);
Enregistrez le texte chiffré dans le fichier, et inversez le processus lors de la lecture du fichier.
Signer le contenu
Cela n'empêchera pas l'utilisateur de modifier le fichier ou de voir son contenu (mais vous vous en fichez, un high-score n'est pas secret) mais vous pourrez détecter si l'utilisateur l'a modifié.
var key = Encoding.UTF8.GetBytes("My secret key");
using (var algorithm = new HMACSHA512(key))
{
var payload = Encoding.UTF8.GetBytes("Hello, world.");
var binaryHash = algorithm.ComputeHash(payload);
var stringHash = Convert.ToBase64String(binaryHash);
}
Enregistrez à la fois la charge utile et le hachage dans le fichier, puis, lors de la lecture du fichier, vérifiez si le hachage enregistré correspond à un hachage nouvellement calculé. Votre clé doit rester secrète.
Crypter le contenu
Exploitez les bibliothèques cryptographiques de .NET pour crypter le contenu avant de l'enregistrer et le décrypter lors de la lecture du fichier.
Prenez l'exemple suivant avec un grain de sel et prenez le temps de comprendre ce que fait chaque élément avant de le mettre en œuvre (oui, vous l'utiliserez pour une raison triviale, mais à l'avenir, vous - ou quelqu'un d'autre - ne l'utiliserez peut-être pas). Faites particulièrement attention à la façon dont vous générez le IV et la clé.
// The initialization vector MUST be changed every time a plaintext is encrypted.
// The initialization vector MUST NOT be reused a second time.
// The initialization vector CAN be saved along the ciphertext.
// See https://en.wikipedia.org/wiki/Initialization_vector for more information.
var iv = Convert.FromBase64String("9iAwvNddQvAAfLSJb+JG1A==");
// The encryption key CAN be the same for every encryption.
// The encryption key MUST NOT be saved along the ciphertext.
var key = Convert.FromBase64String("UN8/gxM+6fGD7CdAGLhgnrF0S35qQ88p+Sr9k1tzKpM=");
using (var algorithm = new AesManaged())
{
algorithm.IV = iv;
algorithm.Key = key;
byte[] ciphertext;
using (var memoryStream = new MemoryStream())
{
using (var encryptor = algorithm.CreateEncryptor())
{
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
using (var streamWriter = new StreamWriter(cryptoStream))
{
streamWriter.Write("MySuperSecretHighScore");
}
}
}
ciphertext = memoryStream.ToArray();
}
// Now you can serialize the ciphertext however you like.
// Do remember to tag along the initialization vector,
// otherwise you'll never be able to decrypt it.
// In a real world implementation you should set algorithm.IV,
// algorithm.Key and ciphertext, since this is an example we're
// re-using the existing variables.
using (var memoryStream = new MemoryStream(ciphertext))
{
using (var decryptor = algorithm.CreateDecryptor())
{
using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
using (var streamReader = new StreamReader(cryptoStream))
{
// You have your "MySuperSecretHighScore" back.
var plaintext = streamReader.ReadToEnd();
}
}
}
}
}