Search code examples
c#stringfilebinarywriter

Problems with writing bytes format of string data in Text File in C#


I have a text file stored locally. I want to store string data in binary format there and then retrieve the data again. In the following code snippet, I have done the conversion.

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
class ConsoleApplication
{
    const string fileName = "AppSettings.dat";

    static void Main()
    {
        string someText = "settings";
        byte[] byteArray = Encoding.UTF8.GetBytes(someText);
        int byteArrayLenght = byteArray.Length;
        using (BinaryWriter writer = new BinaryWriter(File.Open(fileName, FileMode.Create)))
        {
            writer.Write(someText);
        }
        byte[] x = new byte[byteArrayLenght];

        if (File.Exists(fileName))
        {
            using (BinaryReader reader = new BinaryReader(File.Open(fileName, FileMode.Open)))
            {
                x = reader.ReadBytes(byteArrayLenght);
            }
            string str = Encoding.UTF8.GetString(x);
            Console.Write(str);
            Console.ReadKey();
        }
    }
}

In the AppSettings.dat file the bytes are written in the following way enter image description here

But when I have assigned some random value in a byte array and save it in a file using BinaryWriter as I have done in the following code snippet

const string fileName = "AppSettings.dat";

static void Main()
{
    byte[] array = new byte[8];
    Random random = new Random();
    random.NextBytes(array);

    using (BinaryWriter writer = new BinaryWriter(File.Open(fileName, FileMode.Create)))
    {
        writer.Write(array);
    }
}

It's actually saved the data in binary format in the text file, shown in the picture. enter image description here

I don't understand why (in my first case) the byte data converted from string showing human readable format where I want to save the data in non-readable byte format(later case). What's the explanation regarding this?

Is there any way where I can store string data in binary format without approaching brute force?

FYI - I don't want to keep the data in Base64String format, I want it to be in binary format.


Solution

  • If security isn't a concern, and you just don't want the average usage to find your data while meddling into the settings files, a simple XOR will do:

    const string fileName = "AppSettings.dat";
    
    static void Main()
    {
        string someText = "settings";
        byte[] byteArray = Encoding.UTF8.GetBytes(someText);
    
        for (int i = 0; i < byteArray.Length; i++)
        {
            byteArray[i] ^= 255;
        }
    
        File.WriteAllBytes(fileName, byteArray);
    
        if (File.Exists(fileName))
        {
            var x = File.ReadAllBytes(fileName);
    
            for (int i = 0; i < byteArray.Length; i++)
            {
                x[i] ^= 255;
            }
    
            string str = Encoding.UTF8.GetString(x);
            Console.Write(str);
            Console.ReadKey();
        }
    }
    

    It takes advantage of an interesting property of character encoding:

    • In ASCII, the 0-127 range contains the most used characters (a to z, 0 to 9) and the 128-256 range contains only special symbols and accents
    • For compatibility reasons, in UTF-8 the 0-127 range contains the same characters as ASCII, and the 128-256 range have a special meaning (it tells the decoder that the characters are encoded into multiple bytes)

    All I do is flipping the strong-bit of each byte. Therefore, everything in the 0-127 range ends up in the 128-256 range, and vice-versa. Thanks to the property I described, no matter if the text-reader tries to parse in ASCII or in UTF-8, it will only get gibberish.

    Please note that, while it doesn't produce human-readable content, it isn't secure at all. Don't use it to store sensitive data.