简体   繁体   中英

How can I create a file that only my application can modify it?

How can I create a file that only my application can modify? I need it because I have an app that creates a .txt file where user information is stored and I don't want the user to be able to modify it through File Explorer, but my App should be able to create it, modify it and delete it.

this is my code:

        public void Write(List<Queue> Queue)
        {
          try
          {
            CreateFile();
            using (FileStream Stream = new FileStream(Path, FileMode.Open))
            {
                using (StreamWriter file = new StreamWriter(Stream))
                {
                    string Data = JsonSerializer.Serialize(Queue);
                    file.Write(Data);
                    file.Flush();
                    file.Close();
                }
            }
        }
        catch (IOException ex)
        {
            Log.GetInstance().Write(ex.Message);
        }



public void CreateFile()
    {
        if (!FileExist)
        {
            File.Create(Path).Close();
        }
    }

    public List<Queue> ReadFile()
    {
        try
        {
            if (FileExist)
            {
                using (StreamReader file = new StreamReader(Path))
                {
                    string Data= file.ReadToEnd();
                    return JsonSerializer.Deserialize<List<Cola>>(Data);
                }
            }
        }
        catch (JsonException ex)
        {
            Log.GetInstance().Write(ex.Message);
        }
        catch (IOException ex)
        {
            Log.GetInstance().Write(ex.Message);
        }
        return null;
    }

You cannot as far as I know. Users and/or administrators will have access to that file either way. You can, however, detect modification by hashing the file and comparing the hash with the file

You can encrypt the file to prevent tampering. Well, at least any tampering will corrupt the file.

The CLR has a mechanism to encrypt data to a specific user without having to generate and store a key separately. This uses the ProtectedData.Protect() and ProtectedData.Unprotect() mechanism in System.Security.Cryptography .

Here is a test program. Run it one, select 1 to store data, type in something secret then quit. Run it a second time, select 2 to read data and the secret text will appear.

class Program
{
    static void Main(string[] args)
    {
        while (true)
        {
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("Do you want to 1. store data, 2. read data or 0. exit ?");
            Console.ForegroundColor = ConsoleColor.Gray;
            var input = Console.ReadLine();

            if (input.Length == 0 || input[0] == '0') break;

            if (input[0] == '1')
            {
                Console.WriteLine("Type in a very secret message to store:");
                Console.ForegroundColor = ConsoleColor.Yellow;
                var text = Console.ReadLine();
                Console.ForegroundColor = ConsoleColor.Gray;
                if (text.Length > 0)
                {
                    WriteToFile(text);
                }
            }

            if (input[0] == '2')
            {
                if (ReadFromFile(out string text))
                {
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine(text);
                    Console.ForegroundColor = ConsoleColor.Gray;
                }
            }
        }
    }

    const string filename = "data.enc";

    static bool WriteToFile(string text)
    {
        var fn = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), filename);
        var data = Encoding.Unicode.GetBytes(text);
        try
        {
            var cipher = ProtectedData.Protect(data, null, DataProtectionScope.CurrentUser);
            File.WriteAllBytes(fn, cipher);
            Console.WriteLine($"Encrypted {data.Length} bytes in {fn}.");
            return true;
        }
        catch (CryptographicException ex)
        {
            Console.WriteLine("Error encoding data: ");
            Console.WriteLine(ex.ToString());
        }
        catch (IOException ex)
        {
            Console.WriteLine("Error creating file: ");
            Console.WriteLine(ex.ToString());
        }
        return false;
    }

    static bool ReadFromFile(out string text)
    {
        var fn = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), filename);
        try
        {
            var cipher = File.ReadAllBytes(fn);
            var data = ProtectedData.Unprotect(cipher, null, DataProtectionScope.CurrentUser);
            text = Encoding.Unicode.GetString(data);
            Console.WriteLine($"Decrypted {data.Length} bytes from {fn}.");
            return true;

        }
        catch (CryptographicException ex)
        {
            Console.WriteLine("Error decoding data: ");
            Console.WriteLine(ex.ToString());
        }
        catch (IOException ex)
        {
            Console.WriteLine("Error reading file: ");
            Console.WriteLine(ex.ToString());
        }
        text = null;
        return false;
    }
}

scr1

and the contents of data.enc are completely encryted:

scr2

How can I create a file that only my application can modify it?

You can't. Simple as that.

The thing is that administrators can access all files. And the user your running your app with. And hackers of course. ;) Typically you would just store application files in some well established locations, eg it is a de facto standard to put app files in /var/lib/myapp in unix systems. Of course other users will still be able to access those files, but that way you at least lower accidental modifications risk. However this also means that you should never store sensitive data locally .

Encryption is not really an option, because you have to store the encryption key somewhere, which just moves the pile from one place to another. It does make read/write a bit harder, but it doesn't really solve the issue. Unless you don't store the key anywhere, eg you manually provide it on application start or even better during runtime and you ensure it doesn't live too long. Depending on your usecase this may be a valid option.

Modification detection, ie hashing the file, has exactly the same issue: you have to store the hash somewhere. You only force the malicious user to modify two locations instead of one.

Note that using a database engine locally won't help at all. At the end of the day a database is just a fancy file, and you still need to store access keys somewhere.

All in all: if you are storing a non-sensitive data, then put it in application data folder and don't worry about it.

Not sure exactly what your application should do, but the way to achieve this would be to create a new user or group on the computer and run your application as that user. You can then use SetAccessControl to make it so that the user or group as read/write permissions and everyone else has read permissions. This should actually be a Windows service rather then an application.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM