Делать.txt-файл нечитаемый / не редактируемый
У меня есть программа, которая экономит немного .txt файл с рекордом в нем:
// Create a file to write to.
string createHighscore = _higscore + Environment.NewLine;
File.WriteAllText(path, createText);
// Open the file to read from.
string createHighscore = File.ReadAllText(path);
проблема в том, что пользователь может редактировать файл как можно проще – с помощью texteditor. Поэтому я хочу сделать файл нечитаемый / нередактируемом или зашифровать его.
Я думал, что могу сохранить данные в файле ресурсов, но могу ли я писать в файле ресурсов? Или сохранить как .dll, зашифровать / расшифровать его или искать MD5-sum/hash.
10 ответов
вы не можете запретить пользователю изменять файл. Это их компьютер, поэтому они могут делать все, что хотят (вот почему вся проблема DRM... трудна).
поскольку вы сказали, что используете файл для сохранения высокого балла, у вас есть несколько альтернатив. Обратите внимание, что, как уже говорилось ранее, ни один метод не остановит действительно определенного злоумышленника от подделки значения: поскольку ваше приложение работает на компьютере пользователя, он может просто декомпилировать его, посмотрите, как вы защита ценности (получение доступа к любому секрету, используемому в процессе) и действовать соответственно. Но если вы готовы декомпилировать приложение, узнать используемую схему защиты и придумать скрипт/патч, чтобы обойти его, только чтобы изменить номер, который вы можете видеть, ну, пойти на это?
скрыть содержание
это помешает пользователю редактировать файл напрямую, но это не остановит их, как только алгоритм обфускации известный.
var plaintext = Encoding.UTF8.GetBytes("Hello, world.");
var encodedtext = Convert.ToBase64String(plaintext);
сохраните зашифрованный текст в файл и измените процесс при чтении файла.
подписать содержимое
Это не помешает пользователю редактировать файл или видеть его содержимое (но вам все равно, высокий балл не секрет), но вы сможете обнаружить, если пользователь подделал его.
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);
}
сохраните как полезную нагрузку, так и хэш в файле, а затем при чтении файла проверьте, соответствует ли сохраненный хэш недавно вычисленный. Ваш ключ должен храниться в секрете.
шифровать содержимое
используйте криптографические библиотеки .NET для шифрования содержимого перед его сохранением и расшифровкой при чтении файла.
пожалуйста, возьмите следующий пример с солью и потратьте время, чтобы понять, что все делает, прежде чем реализовать его (да, вы будете использовать его по тривиальной причине, но в будущем вы - или кто - то другой-не может). Pay special внимание на то, как вы генерируете IV и ключ.
// 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();
}
}
}
}
}
поскольку вы, похоже, ищете относительно низкую безопасность, я бы рекомендовал пойти на контрольную сумму. Какой-то псевдокод:
string toWrite = score + "|" + md5(score+"myKey") + Environment.NewLine
Если бы счет был 100, это стало бы
100|a6b6b0a8e56e42d8dac51a4812def434
чтобы убедиться, что пользователь не закалил файл, вы можете использовать:
string[] split = readString().split("|");
if (split[1] != md5(split[0]+"myKey")){
alert("No messing with the scores!");
}else{
alert("Your score is "+split[0]);
}
Теперь, конечно, как только кто-то узнает ваш ключ, они могут возиться с этим, что хотят, но я бы рассмотрел это выходит за рамки данного вопроса. Тот же риск относится и к любому механизму шифрования/дешифрования.
одна из проблем, как упоминалось в комментариях ниже, заключается в том, что как только кто-то выяснит ваш ключ (через грубое принуждение), они могут поделиться им, и каждый сможет очень легко изменить свои файлы. Способ решить эту проблему-добавить в ключ что-то специфичное для компьютера. Например, имя пользователя, который вошел в систему, прошло через алгоритма MD5.
string toWrite = score + "|" + md5(score+"myKey"+md5(System.username /**or so**/)) + Environment.NewLine
Это предотвратит "простое совместное использование"ключа.
вероятно, лучше всего защитить весь файл с помощью стандартной безопасности NT и программно изменить список управления доступом, чтобы защитить весь файл от редактирования нежелательными пользователями (за исключением одного олицетворяющего ваше собственное приложение, конечно).
криптография не может помочь здесь, потому что файл может быть редактируемым с помощью обычного текстового редактора (например, notepad
) и конечный пользователь может повредить файл просто добавив дополнительный символ (или опуская по одному слишком.)
существует альтернативный подход, который не требует усилий по программированию...
сообщите своим пользователям, что после того, как они вручную отредактировали весь текстовый файл, они потеряли вашу поддержку. В конце концов, если вы храните эти данные, потому что это требуется вашим приложением. Повреждение его или выполнение рискованной задачи ручного редактирования может привести к ошибкам вашего приложения.
другой альтернативный подход, который включает в себя программирование усилие...
всякий раз, когда вы изменяете файл из своего приложения, вы можете вычислить хэш MD5 или SHA и сохранить его в отдельном файле, и как только вы хотите прочитать или записать его снова, вы собираетесь проверить, что весь файл производит тот же хэш, прежде чем писать на нем снова.
таким образом, пользователь может редактировать файл вручную, но вы будете знать, когда это неожиданный поведение пользователя (если только пользователь вручную вычисляет хэш-когда файл изменен...).
Что-то, что я еще не видел упомянуто, хранит высокий балл на онлайн-доске лидеров. Очевидно, что это решение требует гораздо большего развития, но поскольку вы говорите об игре, вы, вероятно, можете использовать стороннего поставщика, такого как Steam, Origin, Uplay ... Это имеет дополнительное преимущество лидеров, а не только для вашей машины.
вы не можете сохранять данные в dll, и файл ресурсов и txt-файл доступны для редактирования. Похоже, шифрование-единственный способ для вас. Вы можете зашифровать строку перед сохранением в файл txt. Взгляните на эту тему: зашифровать и расшифровать строку
вы можете сериализовать и десериализовать с помощью шифрования с поток cryptostream :
сериализовать файл :
- создать и открыть FileStream в режиме записи
- создайте Cryptostream и передайте свой filestream
- запись содержимого в Cryptostream (шифрование)
десериализовать файл :
- создать и открыть FileStream в режиме чтения
- создайте Cryptostream и передайте типа FileStream
- чтение из Cryptostream (расшифровка)
вы можете найти примеры и более подробная информация здесь :
msdn.microsoft.com/en-us/library/system.security.cryptography.cryptostream.aspx
http://www.codeproject.com/Articles/6465/Using-CryptoStream-in-C
пример :
byte[] key = { 1, 2, 3, 4, 5, 6, 7, 8 }; // Where to store these keys is the tricky part,
byte[] iv = { 1, 2, 3, 4, 5, 6, 7, 8 };
string path = @"C:\path\to.file";
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
// Encryption and serialization
using (var fStream = new FileStream(path, FileMode.Create, FileAccess.Write))
using (var cryptoStream = new CryptoStream(fStream , des.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
BinaryFormatter serializer = new BinaryFormatter();
// This is where you serialize your data
serializer.Serialize(cryptoStream, yourData);
}
// Decryption
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
using (var cryptoStream = new CryptoStream(fs, des.CreateDecryptor(key, iv), CryptoStreamMode.Read))
{
BinaryFormatter serializer = new BinaryFormatter();
// Deserialize your data from file
yourDataType yourData = (yourDataType)serializer.Deserialize(cryptoStream);
}
простое решение:
Чтобы смягчить хакерскую способность пользователя изменять оценку, вы можете написать ее как двоичную, я думаю.
другое решение:
Записать данные в БД SQLite?
вы можете назвать свой файл как то, что не предполагает, что в нем есть таблица баллов (например, YourApp.dat) и зашифровать содержимое.
принятый ответ здесь содержит код для шифрования и дешифрования текста.
обновление
Я также предлагаю использовать несколько Guid
в качестве пароля для шифрования.
вы не можете писать в ресурсы, больше информации есть в ответ
причина, по которой вы не можете изменить строку ресурса во время выполнения, заключается в потому что ресурс компилируется в исполняемый файл. Если вы вернетесь инженер скомпилированный *.exe или *.dll-файл, вы можете увидеть строка в коде. Редактирование уже скомпилированного исполняемого файла никогда не хорошая идея (если вы не пытаетесь взломать ее), но когда вы пытаетесь делать это из кода исполняемых файлов, это просто невозможно, так как файл блокируется во время выполнения.
- вы можете добавить Только Для Чтения или скрытый атрибуты к вашим файлам используя .SetAttributes, но все же пользователь может удалить атрибуты из windows и отредактируйте файл.
пример:
File.SetAttributes(path, File.GetAttributes(path) | FileAttributes.Hidden);
- другой способ, который я мог бы предложить, - сохранить данные в файле с некоторыми
странный расширения, чтобы пользователь не мог думать об этом как о редактируемом или
важный файл. что-то вроде
ghf.ytr
(не могу ничего придумать более странно прямо сейчас!) - я бы также предложил сделать текстовый файл с
.dll
расширение и сохранение его в одной из папок windows, какsystem32
. Таким образом, пользователь будет иметь действительно трудное время, пытаясь выяснить, где информация оценка идти!
вот код, чтобы сделать текстовый файл не редактируется. точно так же вы используете этот метод, чтобы сделать его не читаемым и т. д.
string pathfile = @"C:\Users\Public\Documents\Filepath.txt";
if (File.Exists(pathfile))
{
File.Delete(pathfile);
}
if (!File.Exists(pathfile))
{
using (FileStream fs = File.Create(pathfile))
{
Byte[] info = new UTF8Encoding(true).GetBytes("your text to be written to the file place here");
FileSecurity fsec = File.GetAccessControl(pathfile);
fsec.AddAccessRule(new FileSystemAccessRule("Everyone",
FileSystemRights.WriteData, AccessControlType.Deny));
File.SetAccessControl(pathfile, fsec);
}
}