使.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);
问题是,用户可以尽可能简单地编辑文件 – 用一个文本编辑器。 所以我想使文件不可读/不可编辑或encryption 。
我的想法是,我可以将数据保存在一个资源文件,但我可以写在一个资源文件? 或者将其保存为.dll,对其进行encryption/解密或查找MD5和/散列。
您不能阻止用户修改文件。 这是他们的电脑,所以他们可以做任何他们想要的(这就是为什么整个数字版权pipe理问题是困难的)。
既然你说过你使用这个文件来保存高分,你有两个select。 请注意,如前所述,没有任何方法可以阻止真正确定的攻击者篡改该值:由于您的应用程序正在用户计算机上运行,因此他可以简单地对其进行反编译,查看您如何保护该值(获取任何机密在过程中使用),并采取相应的行动。 但是,如果你愿意反编译一个应用程序,找出所使用的保护scheme,并提出一个脚本/补丁绕过它只改变一个数字,只有你可以看到,那么,去吧?
混淆内容
这将阻止用户直接编辑该文件,但只要知道了模糊处理algorithm,就不会阻止他们。
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); }
将有效载荷和散列保存在文件中,然后在读取文件时检查保存的散列是否与新计算的散列匹配。 你的钥匙必须保密。
encryption内容
利用.NET的encryption库在保存内容之前对内容进行encryption,并在读取文件时将其解密。
请采取下面的例子,花一些时间来理解在实现它之前所做的一切(是的,你会用它来做一个微不足道的原因,但是未来你或者其他人可能不会)。 要特别注意你如何产生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(); } } } } }
由于您似乎寻找相对较低的安全性,我实际上build议去检查。 一些伪代码:
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]); }
现在当然,只要有人知道你的钥匙,他们可以随心所欲地把这件事情搞砸,但我认为这超出了这个问题的范围。 任何encryption/解密机制都适用相同的风险。
其中一个问题,正如下面的评论中所提到的,一旦有人(通过暴力破解)找出你的密钥,他们就可以分享它,每个人都可以很容易地改变他们的文件。 解决这个问题的一个方法是添加一些特定于计算机的密钥。 例如,login的用户的名字,通过md5运行。
string toWrite = score + "|" + md5(score+"myKey"+md5(System.username /**or so**/)) + Environment.NewLine
这将防止密钥被“简单共享”。
也许你最好的select是使用标准的NT安全保护整个文件,并以编程方式更改访问控制列表,以防止不需要的用户编辑整个文件(当然,除了模仿你自己的应用程序之外)。
encryption技术在这里没有帮助,因为文件仍然可以使用常规的文本编辑器(例如notepad
)进行编辑,最终用户可以通过添加一个额外的字符(或者删除一个)来损坏文件。
有一个不涉及编程工作的替代方法…
告诉你的用户,一旦他们手动编辑了整个文本文件,他们就失去了支持。 在一天结束的时候,如果你存储这些数据是因为你的应用程序需要它。 破坏它或执行手动编辑它的风险任务可能会使您的应用程序产生错误。
另一种涉及编程工作的替代方法…
无论何时从应用程序中更改文件,都可以计算MD5或SHA哈希并将其存储在单独的文件中,一旦您想要再次读取或写入文件,就要检查整个文件是否在生成之前生成相同的哈希再写一遍。
这样,用户仍然可以手动编辑文件,但是当用户完成这个意外行为时(除非用户在文件更改时手动计算哈希)。
我还没有看到提到的一件事就是将最高分存储在在线排行榜上。 显然,这个解决scheme需要更多的开发,但是因为你正在谈论一个游戏,你可能会利用像Steam,Origin,Uplay这样的第三方提供商……这不仅仅是为了你的机器。
您无法将数据保存在dll中,并且Resource文件和txt文件都是可编辑的。 这听起来像encryption是唯一的方法给你。 您可以在将string保存到txt文件之前对其进行encryption。 看看这个线程: encryption和解密一个string
您可以使用CryptoStream对其进行序列化和反序列化encryption:
序列化文件:
- 以写入模式创build并打开FileStream
- 创buildCryptostream并传递你的文件stream
- 写内容到Cryptostream(encryption)
反序列化文件:
- 在读取模式下创build并打开FileStream
- 创buildCryptostream并传递你的文件stream
- 从Cryptostream中读取(解密)
你可以在这里find例子和更多的信息:
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); }
简单的scheme:
为了减轻黑客用户改变分数的能力,我们可以把它写成二进制文件。
另一个scheme
写数据在SQLite数据库?
你可以将你的文件命名为不含有分数表的文件(例如YourApp.dat)并encryption内容。
这里接受的答案包含encryption和解密文本的代码。
更新
我也build议使用一些Guid
作为encryption的密码。
您无法在资源中写入, 此答案中存在更多信息
在运行时不能更改资源string的原因是因为资源被编译到可执行文件中。 如果您对已编译的* .exe或* .dll文件进行反向工程,则实际上可以在代码中看到您的string。 编辑一个已经编译好的可执行文件从来不是一个好主意(除非你试图破解它),但是当你试图从可执行文件代码中做到这一点时,就不可能,因为在执行过程中文件被locking了。
- 您可以使用File.SetAttributes将Read Only或Hidden属性添加到文件,但仍然可以从Windows删除属性并编辑该文件。
一个例子:
File.SetAttributes(path, File.GetAttributes(path) | FileAttributes.Hidden);
- 我build议的另一种方法是将数据保存在带有一些奇怪扩展名的文件中,这样用户就不能将其视为可编辑或重要的文件。 像
ghf.ytr
( 现在不能想到更怪异的东西! ) - 我也build议制作一个扩展名为
.dll
的文本文件,并将其保存在一个像system32
这样的Windows文件夹中。 通过这种方式,用户将很难find分数信息在哪里去!
这是一个使文本文件不可编辑的代码。 以同样的方式,你使用这种技术,使其不可读取等
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); } }