Search code examples
c#.netprotobuf-netbinaryformatterbinary-serialization

How to deserialize the data which is already serialized using BinaryFormatter in C#?


I have a ConcurrentDictionary which I serialized using the BinaryFormatter using the below code.

ConcurrentDictionary<string, DateTime> _jobsAck;
var binaryFormatter = new BinaryFormatter();
using (var stream = File.Open(BINARY_FILENAME, FileMode.OpenOrCreate))
{
    binaryFormatter.Serialize(stream, _jobsAck);
}

There are some security issues with the BinaryFormatter (Microsoft: Deserialization risks in use of BinaryFormatter and related types), so now I want to completely get rid of it. I now want to deserialize the content of the file using some other serializer.

I have tried many (XML serializer, NewtonSoft, ProtoBuf) but none is working (all throwing some exceptions). Could someone please help on this?

Target .NET Framework: 4.7.2

I can also go for .NET Standard <= 2.0 as well.

Edit: Approach to handle this case. So it keeps on serializing the content when a job is created. and on application start it loaded the data from file to the dictionary.

enter image description here


Solution

  • As I tried to highlight in the comments of my yesterday's answer, you will never be able to find a secure 3rd party implementation that can deserialize a BinaryFormatter stream because it would just mean the reintroduction of the vulnerabilities of BinaryFormatter. Apart from the most primitive types, BinaryFormatter saves everything with assembly qualified names that can be manipulated in the serialization stream.

    A possible solution (suggested also by others in the comments) is to migrate your data to another format. Steps to achieve it:

    1. Deserialize your legacy contents with BinaryFormatter (you need to do it only once)
    2. Serialize them again with another serializer. I already mentioned a possible alternative that supports also ConcurrentDictionary<TKey, TValue> natively, meaning, no assembly qualified names are stored for it. If I got it correctly, you want to serialize ConcurrentDictionary<string, DateTime> instances, which is completely supported without storing any type names.
    3. After the migration use your new serializer only.

    Please also note that though ConcurrentDictionary<TKey, TValue> was serializable in .NET Framework by regular IFormatters, it is no longer the case in .NET [Core]. So even if you could find a 3rd party implementation it would most likely fail when used from .NET Standard 2.0.