3
\$\begingroup\$

I have to implement WMSAuth in C#: http://wmsauth.org/examples

// The following function was copied from http://wmsauth.org/examples
public static string BuildProtectedURLWithValidity(string password, string media_url, string ip, int valid)
{
    string result = null;
    DateTime cur_date = DateTime.Now;
    TimeZone localzone = TimeZone.CurrentTimeZone;

    DateTime localTime = localzone.ToUniversalTime(cur_date);

    string date_time = localTime.ToString(new CultureInfo("en-us"));

    Int32 Valid = valid;
    string to_be_hashed = ip + password + date_time + Valid.ToString();

    byte[] to_be_hashed_byte_array = new byte[to_be_hashed.Length];

    int i = 0;
    foreach (char cur_char in to_be_hashed)
    {
        to_be_hashed_byte_array[i++] = (byte)cur_char;
    }

    byte[] hash = (new MD5CryptoServiceProvider()).ComputeHash(to_be_hashed_byte_array);

    string md5_signature = Convert.ToBase64String(hash);

    result = media_url + "?server_time=" + date_time + "&hash_value=" + md5_signature + "&validminutes=" + Valid.ToString();
    return (result);
}

The problem is that, although I believe the code above might work for every possible input, it seems to be done without much knowledge of C#, and I have a big concern with the Encoding in the byte to char casting.

So I changed the code to this:

private static string BuildProtectedURLWithValidity(string wmsAuthPassword, string mediaUrl, string clientIp, int validMinutes)
{
    string dateTimeString = DateTime.UtcNow.ToString(new CultureInfo("en-us"));
    string validMinutesString = validMinutes.ToString();

    string stringToBeHashed = clientIp + wmsAuthPassword + dateTimeString + validMinutesString;
    string hashValue;
    using (MD5CryptoServiceProvider md5Provider = new MD5CryptoServiceProvider())
    {
        byte[] bytesToBeHashed = Encoding.UTF8.GetBytes(stringToBeHashed);
        byte[] hashBytes = md5Provider.ComputeHash(bytesToBeHashed);
        hashValue = Convert.ToBase64String(hashBytes);
    }

    string result = mediaUrl + "?server_time=" + dateTimeString + "&hash_value=" + hashValue + "&validminutes=" + validMinutesString;
    return result;
}

But my real concern is that with my attempt to follow the company's naming standards and improve the code readability I might be introducing a bug in already tested code. Would you use the version posted in the the WMSAuth page?

Note: It has to work with the .NET Framework 1.1

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Well, the problem is that the example code provided effectively does a % 256 on the input characters. So it's possible that your version and the example code yield two different values for the same input.

However you said I believe the code above might work for every possible input - I take it then that password will never contain any characters where the wrap-around will play a role? If that's the case then your version should be equivalent.

If you are paranoid then replace Encoding.UTF8.GetBytes in your code with the same loop as used in the example but leave your other refactorings intact.

In fact I would refactor the result into:

string.Format("{0}?server_time={1}&hash_value={2}&validminutes={3}", mediaUrl, dateTimeString, hashValue, validMinutes);

Which means you could also get rid of the validMinutesString.

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.