August 23, 2006

WTF? Can some .NET guru help me out?

Recently I had to figure out some VB.NET code and port it to C#. I am not much of a VB guy, but I figured I could understand some basic stuff. I am having some difficulties, and was hoping someone could explain the brain dead issue I am having. Here is the VB.NET code:


Sub Main()
Dim key_aes128 As String
key_aes128 = Chr(&H5S) & Chr(&H4S) & Chr(&H57S) & Chr(&HF0S) & Chr(&H5CS) & Chr(&HADS) & Chr(&H9AS) & Chr(&H55S) & Chr(&H5S) & Chr(&H4S) & Chr(&H17S) & Chr(&HF0S) & Chr(&H5CS) & Chr(&HADS) & Chr(&H9AS) & Chr(&H55S)
End Sub

Here is the C# code I am trying:


static void Main(string[] args)
{
string key_aes128;
key_aes128 = String.Format( "{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}{13}{14}{15}",
Chr(0x5), Chr(0x4), Chr(0x57), Chr(0xF0), Chr(0x5C), Chr(0xAD), Chr(0x9A), Chr(0x55),
Chr(0x5), Chr(0x4), Chr(0x17), Chr(0xF0), Chr(0x5C), Chr(0xAD), Chr(0x9A), Chr(0x55) );
}
static Char Chr(int i)
{
return Convert.ToChar(i);
}

You would THINK that key_aes128 would be the same. They are CLOSE.... but not actually the same. Anyone know what the heck I am doing wrong? It SHOULD result in the exact same string.

Posted by SilverStr at August 23, 2006 03:46 PM | TrackBack
Comments

The VB.NET Chr() function is real strange one (that's legacy for you). Here's a version on your C# program's Chr that should return the same result:

static Char Chr(int i)
{
byte[] byteBuffer = new byte[2];
byteBuffer[0] = (byte) i;
byteBuffer[1] = 0;

return Encoding.Default.GetChars(byteBuffer)[0];
}

Note there's a couple of assumptions I've made here. First of all, I'm assuming that your current system-default codepage is a single-byte code-page, and second, you're never going to pass anything > 0xFF into your Chr function (because then it does something different).

If you don't mind your ported code depending on the Microsoft.VisualBasic assmebly, and the most important thing for you is compatibility with the VB version, then I'd suggest you set that as a dependency of your C# app, and use the VB Chr function directly:

static Char Chr(int i)
{
return Microsoft.VisualBasic.Strings.Chr(i);
}

Posted by: Dean Harding at August 23, 2006 05:21 PM

Take a step back and think about what you're doing. You're creating an AES key. That should be binary - a byte array - and should go nowhere near a Unicode string. Use:

byte[] key_aes128 =
{ 0x5, 0x4, 0x57, 0xf0, 0x5c, 0xad, 0x9a, 0x55,
0x5, 0x4, 0x17, 0xf0, 0x5c, 0xad, 0x9a, 0x55 };

This could be different from the VB code depending on how the VB code gets a byte array to use with the AES algorithm. You _are_ using System.Security.Cryptography.Rijndael, aren't you? (I'm guessing the name of the class wasn't changed when Rijndael was selected as the AES algorithm).

If you really must use a string I would recommend the use of proper string literal syntax, which VB doesn't support, hence the irritating concatenation:

string key_aes128 =
"\x5\x4\x57\xf0\x5c\xad\x9a\x55" +
"\x5\x4\x17\xf0\x5c\xad\x9a\x55";

Posted by: Mike Dimmick at August 23, 2006 05:25 PM

Well, I'd also agree with Mike that changing the behaviour would be better than trying to copy the VB code, but that's not always possible...

Posted by: Dean Harding at August 23, 2006 05:40 PM

The VB Chr function does more than just return a Char. It determines if you are using single or double byte character set and examines your current culture before returning. So you get a culture specific string. Many of the VB conversion functions work this way. I suspect this might be the issue.

If you look at the disassembled code you'll see what is going on.
http://static.flickr.com/72/223291717_b131cae1d1.jpg

As others have said, the byte array might work better than converting from VB.

Posted by: Walt Ritscher - Thinking about code at August 23, 2006 05:56 PM

Great comments by everyone. Thanks so much.

It appears that the Chr() VB function indeed does more that I originally got from the MSDN docs.

Dean's solution works well. The only difference I did was add a sentry to ensure that nothing larger that 0xFF gets passed in.

From this, I now have a fully working test program mimicking the functionality of the VB.NET app. Now I can refactor it and clean it up.

I really appreciate everyone's insights. Thanks again.

Posted by: Dana Epp at August 23, 2006 06:09 PM