Подтвердить что ты не робот

Сделать файл .txt нечитаемым/uneditable

У меня есть программа, которая сохраняет небольшой .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);

Проблема заключается в том, что пользователь может редактировать файл как можно проще - с помощью текстового редактора. Поэтому я хочу сделать файл нечитаемым /uneditable или зашифровать его.

Я думал, что могу сохранить данные в файле ресурсов, но могу ли я написать файл ресурсов? Или сохраните его как .dll, зашифруйте/расшифруйте его или найдите MD5-sum/hash.

4b9b3361

Ответ 1

Вы не можете запретить пользователю изменять файл. Это их компьютер, поэтому они могут делать все, что им нужно (поэтому проблема с DRM... сложна).

Поскольку вы сказали, что используете файл, чтобы сохранить высокий балл, у вас есть несколько альтернатив. Обратите внимание, что, как ранее говорилось, ни один из методов не остановит действительного атакующего от вмешательства в значение: поскольку ваше приложение запущено на пользовательском компьютере, он может просто декомпилировать его, посмотрите, как вы защищаете значение (получая доступ к любому секретному используемые в процессе) и действуют соответственно. Но если вы хотите декомпилировать приложение, узнайте схему защиты и придумайте script/patch, чтобы обойти это только для изменения числа, которое только вы можете видеть, ну, идите на это?

Обфускация содержимого

Это не позволит пользователю редактировать файл напрямую, но он не остановит их, как только будет известен алгоритм обфускации.

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 для шифрования содержимого перед сохранением и расшифровкой его при чтении файла.

Пожалуйста, примите следующий пример с солью и потратьте время, чтобы понять, что все делает до его реализации (да, вы будете использовать его по тривиальной причине, но в будущем вы - или кто-то другой - не может), Обратите особое внимание на то, как вы генерируете 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();
                }
            }
        }
    }
}

Ответ 2

Поскольку вы, похоже, ищете относительно низкую безопасность, я бы рекомендовал вам получить контрольную сумму. Некоторые псевдокоды:

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

Это предотвратит "просто общий" ключ.

Ответ 3

Наверное, ваш лучший выбор - обеспечить безопасность всего файла с помощью стандартной безопасности NT и программно изменить список управления доступом, чтобы защитить весь файл от редактирования нежелательными пользователями (за исключением того, что вы сами выдаете себя за собственное приложение).

Криптография не может помочь здесь, потому что файл может быть доступен для редактирования с использованием обычного текстового редактора (например, notepad), и конечный пользователь может повредить файл, просто добавив лишний символ (или отбросив его).

Есть альтернативный подход, который не требует усилий по программированию...

Сообщите своим пользователям, что после того, как они вручную отредактировали весь текстовый файл, они потеряли вашу поддержку. В конце концов, если вы храните эти данные, это необходимо для вашего приложения. Коррупция или выполнение рискованной задачи ручного редактирования может привести к возникновению ошибок вашего приложения.

Другой альтернативный подход, который включает в себя усилия по программированию...

Всякий раз, когда вы меняете файл из своего приложения, вы можете вычислить хэш MD5 или SHA и сохранить его в отдельном файле, и как только вы захотите его снова или снова прочитать, вы увидите, что весь файл создает тот же хеш, прежде чем писать на нем снова.

Таким образом, пользователь все равно может редактировать ваш файл вручную, но вы узнаете, когда это неожиданное поведение было сделано пользователем (если только пользователь не вручную вычисляет хэш всякий раз, когда файл изменяется...).

Ответ 4

Что-то, о чем я еще не упоминал, это сохранение высокого балла на онлайн-лиге. Очевидно, что это решение требует гораздо большего развития, но поскольку вы говорите об игре, возможно, вы можете использовать сторонний провайдер, такой как Steam, Origin, Uplay,... Это имеет дополнительное преимущество в отношении лидеров, которые не просто предназначены для вашей машины.

Ответ 5

Вы не можете сохранять данные в dll, и как файл ресурсов, так и файл txt доступны для редактирования. Похоже, шифрование - единственный способ для вас. Вы можете зашифровать строку перед сохранением ее в txt файле. Взгляните на эту тему: Шифровать и расшифровывать строку

Ответ 6

Простое решение:
Чтобы уменьшить хакерскую способность пользователя изменить оценку, вы можете записать ее как двоичную, я думаю.
Другое решение:
Запись данных в SQLite DB?

Ответ 7

Вы можете сериализовать его и десериализовать с помощью шифрования с помощью CryptoStream:

Сериализовать файл:

  • Создание и открытие FileStream в режиме записи
  • Создайте Cryptostream и передайте свой поток
  • Запись содержимого в Cryptostream (шифрование)

Файл десериализации:

  • Создать и открыть FileStream в режиме чтения
  • Создайте Cryptostream и передайте свой поток
  • Чтение из 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);
}

Ответ 8

Вы не можете писать в разделе "Ресурсы", более подробная информация существует в этом ответе

Причина, по которой вы не можете изменить строку ресурса во время выполнения, потому что ресурс компилируется в ваш исполняемый файл. Если вы измените обработать скомпилированный файл *.exe или *.dll, вы можете увидеть строка в коде. Редактирование уже скомпилированного исполняемого файла никогда не была хорошей идеей (если вы не пытаетесь ее взломать), но когда вы пытаетесь сделать это из кода исполняемых файлов, это просто невозможно, так как файл заблокирован во время выполнения.

  • Вы можете добавлять к файлам только для чтения или скрытые атрибуты, используя File.SetAttributes, но пользователь может удалить атрибуты из окон и отредактировать файл.

Пример:

File.SetAttributes(path, File.GetAttributes(path) | FileAttributes.Hidden);
  • Другим способом, который я мог бы предложить, является сохранение данных в файле с помощью некоторых странные расширения, чтобы пользователь не мог думать об этом как о редактируемом или важный файл. somthing like ghf.ytr (Не могу придумать что-нибудь более странно прямо сейчас!)
  • Я также предлагаю создать текстовый файл с расширением .dll и сохранить его в одной из окон, таких как system32. Таким образом, у пользователя будет очень трудное время, пытаясь выяснить, куда идет информация об оценке.

Ответ 9

Вы можете назвать свой файл как нечто, что не предполагает, что в нем есть таблица баллов (например, YourApp.dat) и шифрование содержимого.

Принятый ответ здесь содержит код для шифрования и дешифрования текста.

Обновление
Я также предлагаю использовать Guid как пароль для шифрования.

Ответ 10

Вот код, чтобы сделать текстовый файл недоступным для редактирования. таким же образом вы используете эту технику, чтобы сделать ее нечитаемой и т.д.

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);
    }
}