2

Here is my code:

    public static void Save<T>(T toSerialize, string fileSpec) {
        BinaryFormatter formatter = new BinaryFormatter();
        DESCryptoServiceProvider des = new DESCryptoServiceProvider();

        using (FileStream stream = File.Create(fileSpec)) {
            using (CryptoStream cryptoStream = new CryptoStream(stream, des.CreateEncryptor(key, iv), CryptoStreamMode.Write)) {
                formatter.Serialize(cryptoStream, toSerialize);
                cryptoStream.FlushFinalBlock();
            }
        }
    }

    public static T Load<T>(string fileSpec) {
        BinaryFormatter formatter = new BinaryFormatter();
        DESCryptoServiceProvider des = new DESCryptoServiceProvider();

        using (FileStream stream = File.OpenRead(fileSpec)) {
            using (CryptoStream cryptoStream = new CryptoStream(stream, des.CreateEncryptor(key, iv), CryptoStreamMode.Read)) {
                return (T)formatter.Deserialize(cryptoStream);
            }
        }
    }

Key and iv are both static byte arrays with a length of 8 which I'm using for testing purposes. There error is as follows:

Binary stream '178' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization

Any help is much appreciated!

AnthonyOSX
  • 342
  • 5
  • 15
  • Did you update windows or modify any other DLLs in your project between the time you called save and the time you called load? – Scott Chamberlain Mar 06 '15 at 06:11
  • @ScottChamberlain Yes, is there another method to do what I'm doing without regard for this? I'll be updating my application periodically. – AnthonyOSX Mar 06 '15 at 06:18
  • 1
    Shouldn't `Load` be using `CreateDecryptor`, not `CreateEncryptor`? – Mike Zboray Mar 06 '15 at 06:20
  • `BinaryFormater` does not tolerate version changes, you are screwed. You are not supposed to persist data serialized by BinaryFormatter, you need to use XMLSeralizer or a 3rd party binary format like ProtoBuf. BinaryFormatter is only intended to be used for IPC communications. – Scott Chamberlain Mar 06 '15 at 06:45
  • @ScottChamberlain I originally was using XMLSerializer however I wasn't able to get it working with my classes as they're subclasses of a root class. – AnthonyOSX Mar 06 '15 at 14:07
  • @Swizzbeat Well the reason BinaryFormatter works when XMLSeariazer does not is because BinaryFormatter will fail on deserialization if a class changes. Those more strict rules lets more stuff be serialized, but when you break the rules you get nothing back. BinaryFormatter may not have been your real problem *this time*, but it is going come back and bite you. – Scott Chamberlain Mar 06 '15 at 14:11
  • @ScottChamberlain What would you suggest I be using instead? – AnthonyOSX Mar 06 '15 at 14:16
  • 2
    "you need to use XMLSeralizer or a 3rd party binary format like ProtoBuf. BinaryFormatter is only intended to be used for IPC communications." – Scott Chamberlain Mar 06 '15 at 14:35
  • @ScottChamberlain Thanks for the help, I'm looking into ProtoBuf now :) – AnthonyOSX Mar 06 '15 at 14:39

1 Answers1

3

One small typo: your Load method should use des.CreateDecryptor, like this:

public static T Load<T>(string fileSpec)
{
    BinaryFormatter formatter = new BinaryFormatter();
    DESCryptoServiceProvider des = new DESCryptoServiceProvider();

    using (FileStream stream = File.OpenRead(fileSpec))
    {
        using (CryptoStream cryptoStream = 
               new CryptoStream(stream, des.CreateDecryptor(key, iv),
                                CryptoStreamMode.Read))
        {
            return (T)formatter.Deserialize(cryptoStream);
        }
    }
}
Christopher Stevenson
  • 2,843
  • 20
  • 25