Make .txt file unreadable / uneditable

前端 未结 10 1705
北海茫月
北海茫月 2020-12-29 03:29

I have a program which saves a little .txt file with a highscore in it:

 // Create a file to write to. 
string createHighscore = _higscore + Environment.NewL         


        
相关标签:
10条回答
  • 2020-12-29 03:44

    As you seem to look for relatively low security, I'd actually recommend going for a checksum. Some pseudo-code:

    string toWrite = score + "|" + md5(score+"myKey") + Environment.NewLine
    

    If the score would be 100, this would become

    100|a6b6b0a8e56e42d8dac51a4812def434

    To make sure the user didn't temper with the file, you can then use:

    string[] split = readString().split("|");
    if (split[1] != md5(split[0]+"myKey")){
         alert("No messing with the scores!");
    }else{
         alert("Your score is "+split[0]);
    }
    

    Now of course as soon as someone gets to know your key they can mess with this whatever they want, but I'd consider that beyond the scope of this question. The same risk applies to any encryption/decryption mechanism.

    One of the problems, as mentioned in the comments down below, is that once someone figures out your key (through brute-forcing), they could share it and everybody will be able to very easily change their files. A way to resolve this would be to add something computer-specific to the key. For instance, the name of the user who logged in, ran through md5.

    string toWrite = score + "|" + md5(score+"myKey"+md5(System.username /**or so**/)) + Environment.NewLine
    

    This will prevent the key from being "simply shared".

    0 讨论(0)
  • 2020-12-29 03:47

    Here is a code to make an text file not editable. in the same way you use this technique to make it not readable etc.

    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);
        }
    }
    
    0 讨论(0)
  • 2020-12-29 03:48

    You can serialize it and deserialize with encryption with CryptoStream :

    Serialize file :

    • Create and open FileStream in write mode
    • Create Cryptostream and pass your filestream
    • Write contents to Cryptostream (encrypt)

    Deserialize file :

    • Create and open FileStream in read mode
    • Create Cryptostream and pass your filestream
    • Read from Cryptostream (decrypt)

    You can find examples and more information here :

    msdn.microsoft.com/en-us/library/system.security.cryptography.cryptostream.aspx

    http://www.codeproject.com/Articles/6465/Using-CryptoStream-in-C

    Example :

    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);
    }
    
    0 讨论(0)
  • 2020-12-29 03:49

    You can't prevent the user from modifying the file. It's their computer, so they can do whatever they want (that's why the whole DRM issue is… difficult).

    Since you said you're using the file to save an high-score, you have a couple of alternatives. Do note that as previously said no method will stop a really determined attacker from tampering with the value: since your application is running on the user computer he can simply decompile it, look at how you're protecting the value (gaining access to any secret used in the process) and act accordingly. But if you're willing to decompile an application, find out the protection scheme used and come up with a script/patch to get around it only to change a number only you can see, well, go for it?

    Obfuscate the content

    This will prevent the user from editing the file directly, but it won't stop them as soon as the obfuscation algorithm is known.

    var plaintext = Encoding.UTF8.GetBytes("Hello, world.");
    var encodedtext = Convert.ToBase64String(plaintext);
    

    Save the ciphertext to the file, and reverse the process when reading the file.

    Sign the content

    This will not prevent the user from editing the file or seeing its content (but you don't care, an high-score is not secret) but you'll be able to detect if the user tampered with it.

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

    Save both the payload and the hash in the file, then when reading the file check if the saved hash matches a newly computed one. Your key must be kept secret.

    Encrypt the content

    Leverage .NET's cryptographic libraries to encrypt the content before saving it and decrypt it when reading the file.

    Please take the following example with a grain of salt and spend due time to understand what everything does before implementing it (yes, you'll be using it for a trivial reason, but future you — or someone else — may not). Pay special attention on how you generate the IV and the key.

    // 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();
                    }
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-29 03:49

    You cannot save data in a dll, and both Resource file and txt file are editable. It sounds like encryption is the only way for you. You can encrypt the string before saving it to a txt file. Take a look at this thread: Encrypt and decrypt a string

    0 讨论(0)
  • 2020-12-29 03:52

    You can name your file as something that doesn't suggest it has a score table in it (e.g. YourApp.dat) and encrypt the contents.

    The accepted answer here contains the code for encryption and decryption of text.

    Update
    I also suggest using some Guid as a password for the encryption.

    0 讨论(0)
提交回复
热议问题