2007-02-01

string.GetHashCode

I recently developed a simple support application that allows users on a PC to provide a one-off security number to a Pocket PC user and when entered the PPC will perform a specific support function.

I used the same class to generate these security codes in both the desktop and compact framework applications, tested it quite thoroughly and it all seemed to work fine. However once deployed it became evident that the codes provided by our support department were being rejected by the PPC as invalid. So what went wrong?

Seeing as the same class was used for both applications I thought it would be okay to test the encoding/decoding of command numbers on only a single platform, and this was my mistake! The routines use string.GetHashCode() to add a checksum to the end of the security codes just to prevent the user from performing actions without authorisation. For reasons I cannot imagine the implementation of string.GetHashCode() is different in the compact framework from the one in the full .NET framework. It was due to the result of this method being different on the two platforms that the codes were being rejected.

So, I have disassembled the compact framework version and used that in my desktop application instead, and now it works just fine. Here is the code....

public int MyHashCode(string value)
{
int charIndex = 0;
int num1;
int num2 = 0x1505;
int num3 = num2;
char currentChar;
while (charIndex < value.Length)
{
currentChar = value[charIndex];
num1 = (int)currentChar;
num2 = ((num2 << 5) + num2) ^ num1;

if (charIndex == value.Length - 1)
break;

num1 = value[charIndex + 1];
if (num1 == 0)
{
break;
}
num3 = ((num3 << 5) + num3) ^ num1;
charIndex += 2;
}
return (num2 + (num3 * 0x5d588b65));
}

2 comments:

Anonymous said...

This would seem to overflow:

(num2 + (num3 * 0x5d588b65));

David

NiceGuyUK said...

Microsoft's .Net BCL team don't guarantee hashing algorithm compatibility between framework runtimes. Switch your app from .Net 1.1 to 2.0 or 2.0 to 3.0 and you'll see it. This is so they can make continued improvements to hash distributions. I'd imagine this difference is very apparent between the desktop and compact editions of the framework.