Olivier
Olivier

Reputation: 11

My MD5 Hash of an object give me different result depending of the program who call it

I migrate an old program to a new version (console app to WPF) and I encounter a problem with the md5 hash It's an import program (take XML, serialize it, convert data and store in DB). To avoid duplicate datas, i set a hash of the object before the import to check if the data already exists. This console program is old and note user-friendly for a non IT person, so I need to put it into a WPF version, easier to use :) BUT ! When i ask the Hash, i get a different result >_<

How it shoud work :

All of this work well, but I get another result between the console and WPF...

Versions of the Frameworks :

I tried to get Hash of each members of the object (ProgramHashLib.GenerateKey(phm.Casting) by example) and i got the same result in each version... so i don't think the Framework is responsible... I checked all the items of the object and they were the same...

public abstract class ProgramHashLib { public static String GenerateKey(Object sourceObject) { String hashString;

        //Catch unuseful parameter values
        if (sourceObject == null)
        {
            throw new ArgumentNullException("Null as parameter is not allowed");
        }
        else
        {
            //We determine if the passed object is really serializable.
            try
            {
                //Now we begin to do the real work.
                hashString = ComputeHash(ObjectToByteArray(sourceObject));
                return hashString;
            }
            catch (AmbiguousMatchException ame)
            {
                throw new ApplicationException("Could not definitely decide if object is serializable. Message:" + ame.Message);
            }
        }
    }

    private static string ComputeHash(byte[] objectAsBytes)
    {
        MD5 md5 = new MD5CryptoServiceProvider();
        try
        {
            byte[] result = md5.ComputeHash(objectAsBytes);

            // Build the final string by converting each byte
            // into hex and appending it to a StringBuilder
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < result.Length; i++)
            {
                sb.Append(result[i].ToString("X2"));
            }

            // And return it
            return sb.ToString();
        }
        catch (ArgumentNullException ane)
        {
            //If something occurred during serialization, 
            //this method is called with a null argument. 
            Console.WriteLine("Hash has not been generated.");
            return null;
        }
    }

    private static readonly Object locker = new Object();

    private static byte[] ObjectToByteArray(Object objectToSerialize)
    {
        MemoryStream fs = new MemoryStream();
        BinaryFormatter formatter = new BinaryFormatter();
        try
        {
            //Here's the core functionality! One Line!
            //To be thread-safe we lock the object
            lock (locker)
            {
                formatter.Serialize(fs, objectToSerialize);
            }
            return fs.ToArray();
        }
        catch (SerializationException se)
        {
            Console.WriteLine("Error occurred during serialization. Message: " + se.Message);
            return null;
        }
        finally
        {
            fs.Close();
        }
    }
}

Upvotes: 0

Views: 933

Answers (1)

Olivier
Olivier

Reputation: 11

OKAY ! So it was a problem with the Framework. I set the WPF to 3.5 and it was OK I just had to redo some functions :

  • await/async don't work in 3.5 so search and find AsyncBridge for 3.5...
  • FileHelpers stopped the compilation so i was forced to use the 2.0 instead of the 3.5

I'm not super satisfied with having to downgrade, but it work at least :(

Thanks to everyone who read that and tried to help me ! :)

Upvotes: 1

Related Questions