none
Does .NET Framework SP1 change MD5 encryption algorithm? Any ideas? RRS feed

  • Question

  •  

    We had Windows Server 2003 Standard Edition with Service Pack 1 and .NET Framework 2.0 installed.

     

    After we upgraded the server with Service Pack 2 and .NET Framework 2.0 Service Pack 1, we noticed that our .NET application stopped returning correct values for encrypted passwords.

     

    We use .NET-based MD5 Crypto Service Provider:

    MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();

    TF8Encoding encoder = new UTF8Encoding();

     

    Anyone had a similar issue or may know a work around?

    Friday, April 25, 2008 7:34 PM

Answers

  • Wild guess: http://support.microsoft.com/kb/940521/

     

    It is all too common that people try to treat random binary data as a string...

     

    Best regards,

    Johan Stenberg

    Monday, April 28, 2008 1:18 AM
    Moderator
  • CyrexCore2k and Johan,

     

    Thank you for your help. Finally I made it work!

    As you pointed out .NET2.0 SP1 did not change MD5 algorithm but it changed defaults for UTF8Encoding which was the cause of my issue.

    For the benefits of the forum readers who may have the same issue, here is how I modified my earlier posted code and now it works:

    --------------

    public static string ComputeHash(string username, string password)

    {

    Encoding encoder = Encoding.UTF8.Clone() as Encoding;

    encoder.EncoderFallback = new EncoderReplacementFallback(string.Empty);

    encoder.DecoderFallback = new DecoderReplacementFallback(string.Empty);

    MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();

    return encoder.GetString(md5.ComputeHash(encoder.GetBytes(string.Concat(username, password))));

    }

    --------------


    Thank you again.

    Thursday, May 1, 2008 3:45 PM

All replies

  • Why are you defining a UTF encoder? Usually MD5 hashes are stored as Base64 char arrays.
    Friday, April 25, 2008 9:59 PM
  • I am not sure. It was done by our consultant. But I know everything worked flawlessly before the system update...

     

    Friday, April 25, 2008 10:19 PM
  • The MD5 algorithm wouldn't have changed but I wouldn't be too surprised if the UTF encoder were slightly different. Can you post the lines of code where the hash is actually computed and stored? If it uses the UTF encoder you might be in trouble.

    Also I'd imagine you have the hashes stored somewhere and you're using this method to create a hash from a password on some kind of log in screen. Can you post an example of two hashes that should match but don't?
    Saturday, April 26, 2008 12:36 AM
  • Wild guess: http://support.microsoft.com/kb/940521/

     

    It is all too common that people try to treat random binary data as a string...

     

    Best regards,

    Johan Stenberg

    Monday, April 28, 2008 1:18 AM
    Moderator
  • CyrexCore2k and Johan,

     

    Thank you for your reply.

    The support article that Johan is suggested talks about UTF encoder changes and offer the folowing resolution:

    ------------------------------------
    RESOLUTION

    The new default behavior is equivalent to setting the replacement fallbacks to U+FFFD instead of the empty string. If you would prefer to use the old behavior in a program, a program can create UTF8Encoding with the replacement fallbacks set to empty strings. If you set an EncoderReplacementFallback("") class and a DecoderReplacementFallback("") class, the fallbacks remove the invalid data. However, if you set an EncoderReplacementFallback("") class and a DecoderReplacementFallback("") class, the security issue that was corrected by the new default behavior will still exist.
    ------------------------------------
     
    The method we use in our code to hash the password is the following:
    ------------------------------------

    public static string ComputeHash(string username, string password)

    {

    MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();

    UTF8Encoding encoder = new UTF8Encoding();

    return encoder.GetString(md5.ComputeHash(encoder.GetBytes(string.Concat(username, password))));

    }

    ------------------------------------
     
    I am not sure how and where I should set replacement fallbacks for encoding to empty string ( EncoderReplacementFallback("") )
    Can you point out how to implement the suggested resolution in our code?
     
     
    Tuesday, April 29, 2008 3:27 PM
  • I would strongly advice against using UTFEncoding.GetString() from random bytes of data. A binary blob is *not* a string. Doing this is what caused the problem in the first place.

     

    http://blogs.msdn.com/shawnfa/archive/2005/11/10/491431.aspx

    http://blogs.msdn.com/shawnfa/archive/2004/02/20/77396.aspx

     

    Use Convert.ToBase64String instead!

     

    Best regards,

    Johan Stenberg

    Tuesday, April 29, 2008 5:27 PM
    Moderator
  • I understand that using Convert.ToBase64String instead of UTF8Encoding is better but we did not do it this way and it worked just fine before the upgrade.

    Stop using UTF8Encoding is not an option since we already have thousand passwords encrypted this way and its one way encryption. So we just need to make sure it will continue encrypt/encode exactly the same way as it was before Service Pack installed.

    I need to some help/directions how to modify our code or make any other changes so it will continue encrypting the old way.

    Tuesday, April 29, 2008 8:51 PM
  • Tuesday, April 29, 2008 10:25 PM
    Moderator
  • Actually it is possible. While the MD5 hash is not reversible the UTF8Encoding conversion that converted the bytes to a UTF8 string may be.

    Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(YourUTF8Encoding))

    However, this /may/ not work as expected. You should generate a few md5 hashes and convert them to Base64Strings as well as converting them to UTF8 and then back to Base64 to see if the result is the same. Though obviously this would have to be done on a prior version of .Net.

    If you did find that it worked you could use this method to convert all the passwords in your database and begin using base64 strings.
    Wednesday, April 30, 2008 1:25 AM
  • CyrexCore2k and Johan,

     

    Thank you for your help. Finally I made it work!

    As you pointed out .NET2.0 SP1 did not change MD5 algorithm but it changed defaults for UTF8Encoding which was the cause of my issue.

    For the benefits of the forum readers who may have the same issue, here is how I modified my earlier posted code and now it works:

    --------------

    public static string ComputeHash(string username, string password)

    {

    Encoding encoder = Encoding.UTF8.Clone() as Encoding;

    encoder.EncoderFallback = new EncoderReplacementFallback(string.Empty);

    encoder.DecoderFallback = new DecoderReplacementFallback(string.Empty);

    MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();

    return encoder.GetString(md5.ComputeHash(encoder.GetBytes(string.Concat(username, password))));

    }

    --------------


    Thank you again.

    Thursday, May 1, 2008 3:45 PM