tafkab76
tafkab76

Reputation: 475

How to read a binary formatted string from a file?

I want to store a string in a file in a way, that it can't be (easily) read. So I use a BinaryFormatter like this:

using (FileStream fs = File.Create(sfDialog.FileName, 2048, FileOptions.None))
{
    BinaryFormatter bf = new BinaryFormatter();
    bf.Serialize(fs, Encoding.Unicode.GetBytes(this.BodyText));
}

where this.BodyText is the string to save.

Now I'm struggling to read it back from the file. I tried BinaryReader without success, so I guess, I have to use a BinaryFormatter. I tried the Deserialize method, but it returns an object which can´t be cast to a string. Also Convert.ToBase64String can't be used on an object.

Does anyone know how to solve my problem?

Upvotes: 1

Views: 1087

Answers (4)

zdimension
zdimension

Reputation: 1084

Try this :

using (FileStream fs = File.Create(sfDialog.FileName, 2048, FileOptions.None))
{
    BinaryFormatter deserializer = new BinaryFormatter();
    deserializedObject = System.Text.Encoding.Unicode.GetString((byte[])deserializer.Deserialize(memoryStream));
}

Upvotes: 0

Fabio Salvalai
Fabio Salvalai

Reputation: 2509

If you want the string not to be easily readable, you should use a proper encryption.

For instance, you could use DPAPI who will use your windows credentials as the key to your encryption. (more details about the pros/cons of that concept here)

Or you can read Josh Galloway's article exploring 3 different approaches, where the third looks promising, even if I haven't tried it myself, but the cool part is that it doesn't need your encrypted data to be in a .config file.)

Also, regarding the original question, don't forget that since you called

Encoding.Unicode.GetBytes(this.BodyText)

you will need to call the Encoding service to get the Unicode string out of your byte array when deserializing:

Encoding.Unicode.GetString(myByteArray);

Upvotes: 0

Daniel Hilgarth
Daniel Hilgarth

Reputation: 174467

I agree with the others, you should be using some proper encryption instead of this.

But to answer your actual question: You are serializing a byte array. So that's what you get when you deserialize it.

So, after deserializing, cast to byte[] and convert this byte array to a string:

var s = Encoding.Unicode.GetString((byte[])deserializedValue);

Upvotes: 2

Rakin
Rakin

Reputation: 1279

Use this function to Encrypt & Decrypt.

    string passPhrase = "Pasword";        // can be any string
    string saltValue = "sALtValue";        // can be any string
    string hashAlgorithm = "SHA1";             // can be "MD5"
    int passwordIterations = 7;                  // can be any number
    string initVector = "~1B2c3D4e5F6g7H8"; // must be 16 bytes
    int keySize = 256;                // can be 192 or 128

    private string Encrypt(string data)
    {
        byte[] bytes = Encoding.ASCII.GetBytes(this.initVector);
        byte[] rgbSalt = Encoding.ASCII.GetBytes(this.saltValue);
        byte[] buffer = Encoding.UTF8.GetBytes(data);
        byte[] rgbKey = new PasswordDeriveBytes(this.passPhrase, rgbSalt, this.hashAlgorithm, this.passwordIterations).GetBytes(this.keySize / 8);
        RijndaelManaged managed = new RijndaelManaged();
        managed.Mode = CipherMode.CBC;
        ICryptoTransform transform = managed.CreateEncryptor(rgbKey, bytes);
        MemoryStream stream = new MemoryStream();
        CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Write);
        stream2.Write(buffer, 0, buffer.Length);
        stream2.FlushFinalBlock();
        byte[] inArray = stream.ToArray();
        stream.Close();
        stream2.Close();
        return Convert.ToBase64String(inArray);
    }

    private string Decrypt(string data)
    {
        byte[] bytes = Encoding.ASCII.GetBytes(this.initVector);
        byte[] rgbSalt = Encoding.ASCII.GetBytes(this.saltValue);
        byte[] buffer = Convert.FromBase64String(data);
        byte[] rgbKey = new PasswordDeriveBytes(this.passPhrase, rgbSalt, this.hashAlgorithm, this.passwordIterations).GetBytes(this.keySize / 8);
        RijndaelManaged managed = new RijndaelManaged();
        managed.Mode = CipherMode.CBC;
        ICryptoTransform transform = managed.CreateDecryptor(rgbKey, bytes);
        MemoryStream stream = new MemoryStream(buffer);
        CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Read);
        byte[] buffer5 = new byte[buffer.Length];
        int count = stream2.Read(buffer5, 0, buffer5.Length);
        stream.Close();
        stream2.Close();
        return Encoding.UTF8.GetString(buffer5, 0, count);
    }

Upvotes: 1

Related Questions