1

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?

4
  • 1
    If you want the string not to be easily readable, you should really consider a proper encryption. Commented Oct 5, 2015 at 12:41
  • I suggest you to convert your string into byte[] and xor it's elements with some value. Commented Oct 5, 2015 at 12:44
  • 1
    If you don't want it easily read, why not encrypt it instead? Commented Oct 5, 2015 at 12:45
  • You need to include a length of the string or an End-Character in the save file. You are saving 2048 bytes, but when you read the string your string may only be 54 characters so you don't know where the end of the string is located. Commented Oct 5, 2015 at 13:14

4 Answers 4

2

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);
Sign up to request clarification or add additional context in comments.

1 Comment

Accepted answer, because it actually answers my question perfectly. Of cause all recommendations for using decryption are considerable and probably more elegant than using binary formatting, but since the data isn´t really secret - actually I just want to hide the fact that it´s plain HTML - I will go with this one.
1

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

Comments

0

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

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.