Bitwise operations: Converting from Java to VB.NET

Arokh

Centurion
Joined
Apr 11, 2006
Messages
124
Hi
I need the MD4 Hash algorithm and since I couldn't find it in .NET,
I looked for libraries in the Web.
The only thing I found was something written in Java.
Now I'm trying to convert the source.

I fixed all the syntax errors but it seems I converted some bitwise operators wrongly.

Javacode:
Visual Basic:
      int X0 =  (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16 | in[i++] << 24;
      int X1 =  (in[i++] & 0xFF) | (in[i++] & 0xFF) << 8 | (in[i++] & 0xFF) << 16 | in[i++] << 24;
...

      int aa, bb, cc, dd;

      aa = a;  bb = b;  cc = c;  dd = d;

      aa += ((bb & cc) | ((~bb) & dd)) + X0;
      aa = aa <<  3 | aa >>> -3;
      dd += ((aa & bb) | ((~aa) & cc)) + X1;
      dd = dd <<  7 | dd >>> -7;
      cc += ((dd & aa) | ((~dd) & bb)) + X2;
      cc = cc << 11 | cc >>> -11;
      bb += ((cc & dd) | ((~cc) & aa)) + X3;
      bb = bb << 19 | bb >>> -19;
...

      aa += ((bb & (cc | dd)) | (cc & dd)) + X0 + 0x5a827999;
      aa = aa <<  3 | aa >>> -3;
      dd += ((aa & (bb | cc)) | (bb & cc)) + X4 + 0x5a827999;
      dd = dd <<  5 | dd >>> -5;
      cc += ((dd & (aa | bb)) | (aa & bb)) + X8 + 0x5a827999;
      cc = cc <<  9 | cc >>> -9;
      bb += ((cc & (dd | aa)) | (dd & aa)) + X12 + 0x5a827999;
      bb = bb << 13 | bb >>> -13;
...

      aa += (bb ^ cc ^ dd) + X0 + 0x6ed9eba1;
      aa = aa <<  3 | aa >>> -3;
      dd += (aa ^ bb ^ cc) + X8 + 0x6ed9eba1;
      dd = dd <<  9 | dd >>> -9;
      cc += (dd ^ aa ^ bb) + X4 + 0x6ed9eba1;
      cc = cc << 11 | cc >>> -11;
      bb += (cc ^ dd ^ aa) + X12 + 0x6ed9eba1;
      bb = bb << 15 | bb >>> -15;
...

      a += aa; b += bb; c += cc; d += dd;

My VB.NET code:
Visual Basic:
        Dim X0 As Integer = (b(Add(i)) And &HFF) Or (b(Add(i)) And &HFF) << 8 Or (b(Add(i)) And &HFF) << 16 Or b(Add(i)) << 24
        Dim X1 As Integer = (b(Add(i)) And &HFF) Or (b(Add(i)) And &HFF) << 8 Or (b(Add(i)) And &HFF) << 16 Or b(Add(i)) << 24
...

        Dim aa, bb, cc, dd As Integer

        aa = A
        bb = Me.B
        cc = C
        dd = D

        aa += ((bb And cc) Or ((Not bb) And dd)) + X0
        aa = aa << 3 Or aa >> -3
        dd += ((aa And bb) Or ((Not aa) And cc)) + X1
        dd = dd << 7 Or dd >> -7
        cc += ((dd And aa) Or ((Not dd) And bb)) + X2
        cc = cc << 11 Or cc >> -11
        bb += ((cc And dd) Or ((Not cc) And aa)) + X3
        bb = bb << 19 Or bb >> -19
...

        aa += ((bb And (cc Or dd)) Or (cc And dd)) + X0 + &H5A827999
        aa = aa << 3 Or aa >> -3
        dd += ((aa And (bb Or cc)) Or (bb And cc)) + X4 + &H5A827999
        dd = dd << 5 Or dd >> -5
        cc += ((dd And (aa Or bb)) Or (aa And bb)) + X8 + &H5A827999
        cc = cc << 9 Or cc >> -9
        bb += ((cc And (dd Or aa)) Or (dd And aa)) + X12 + &H5A827999
        bb = bb << 13 Or bb >> -13
...

        aa += (bb Xor cc Xor dd) + X0 + &H6ED9EBA1
        aa = aa << 3 Or aa >> -3
        dd += (aa Xor bb Xor cc) + X8 + &H6ED9EBA1
        dd = dd << 9 Or dd >> -9
        cc += (dd Xor aa Xor bb) + X4 + &H6ED9EBA1
        cc = cc << 11 Or cc >> -11
        bb += (cc Xor dd Xor aa) + X12 + &H6ED9EBA1
        bb = bb << 15 Or bb >> -15
...

        A += aa
        Me.B += bb
        C += cc
        D += dd

It throws an "A first chance exception of type 'System.OverflowException' occurred in HashLib.dll" on:
Visual Basic:
cc += ((dd And aa) Or ((Not dd) And bb)) + X14

The error most likly results from converting the operator >>> to >>,
since VB.NET doesn't have that one.

How can I get the "Unsigned" right shift to work in VB.NET?
 
Ahh nice.
Looks like he used the same source for conversion I did.
But I'm aiming for a more "literal" conversion since the source has a nice structure,
allowing "easily" adding other hash algorithms, which (maybe) I'm planning to do.

Also his conversion doesn't allow me to pass only part of the ToBeHashedBytes and then continue with the next part and so on,
which is a requirement since I'm going to hash files with sizes from 300MB - 3GB.

Side Note: I need the Ed2k Hash which uses the MD4 hash.

Also: Speed is also important since ultimatley my goal would be reading a file only once and
get the CRC, MD5, SHA1 & TTH hash and that as fast as possible.

I found a RFC which describes the algorithm nicely, but it uses circular shifting which I also don't know how to do *sigh*.

Just out of curiosity:
If I use Unsigned Integers, wouldn't that solve the shifting problem?

If not any info for Unsigned shifting or circular shifting would be great.

If you are still curious about unsigned shifts I can certainly have a look and see what I can dig up...
Your help is (as always) very appreciated :)
 
I get the same results as the java code with the following VB.Net code. I had to remove the integer overflow checks in the advanced compile options for the project.

Note - you have to cast the bytes to a larger type before shifting them left, hence the CUInt.

I'll try and tidy it up some.

Visual Basic:
    Public Sub Transform(ByVal bytes() As Byte, ByVal i As Integer)

        Dim x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 As UInteger
        x0 = (bytes(i) And &HFFUI) Or (bytes(i + 1) And &HFFUI) << 8 Or (bytes(i + 2) And &HFFUI) << 16 Or CUInt(bytes(i + 3)) << 24
        i += 4
        x1 = (bytes(i) And &HFFUI) Or (bytes(i + 1) And &HFFUI) << 8 Or (bytes(i + 2) And &HFFUI) << 16 Or CUInt(bytes(i + 3)) << 24
        i += 4
        x2 = (bytes(i) And &HFFUI) Or (bytes(i + 1) And &HFFUI) << 8 Or (bytes(i + 2) And &HFFUI) << 16 Or CUInt(bytes(i + 3)) << 24
        i += 4
        x3 = (bytes(i) And &HFFUI) Or (bytes(i + 1) And &HFFUI) << 8 Or (bytes(i + 2) And &HFFUI) << 16 Or CUInt(bytes(i + 3)) << 24
        i += 4
        x4 = (bytes(i) And &HFFUI) Or (bytes(i + 1) And &HFFUI) << 8 Or (bytes(i + 2) And &HFFUI) << 16 Or CUInt(bytes(i + 3)) << 24
        i += 4
        x5 = (bytes(i) And &HFFUI) Or (bytes(i + 1) And &HFFUI) << 8 Or (bytes(i + 2) And &HFFUI) << 16 Or CUInt(bytes(i + 3)) << 24
        i += 4
        x6 = (bytes(i) And &HFFUI) Or (bytes(i + 1) And &HFFUI) << 8 Or (bytes(i + 2) And &HFFUI) << 16 Or CUInt(bytes(i + 3)) << 24
        i += 4
        x7 = (bytes(i) And &HFFUI) Or (bytes(i + 1) And &HFFUI) << 8 Or (bytes(i + 2) And &HFFUI) << 16 Or CUInt(bytes(i + 3)) << 24
        i += 4
        x8 = (bytes(i) And &HFFUI) Or (bytes(i + 1) And &HFFUI) << 8 Or (bytes(i + 2) And &HFFUI) << 16 Or CUInt(bytes(i + 3)) << 24
        i += 4
        x9 = (bytes(i) And &HFFUI) Or (bytes(i + 1) And &HFFUI) << 8 Or (bytes(i + 2) And &HFFUI) << 16 Or CUInt(bytes(i + 3)) << 24
        i += 4
        x10 = (bytes(i) And &HFFUI) Or (bytes(i + 1) And &HFFUI) << 8 Or (bytes(i + 2) And &HFFUI) << 16 Or CUInt(bytes(i + 3)) << 24
        i += 4
        x11 = (bytes(i) And &HFFUI) Or (bytes(i + 1) And &HFFUI) << 8 Or (bytes(i + 2) And &HFFUI) << 16 Or CUInt(bytes(i + 3)) << 24
        i += 4
        x12 = (bytes(i) And &HFFUI) Or (bytes(i + 1) And &HFFUI) << 8 Or (bytes(i + 2) And &HFFUI) << 16 Or CUInt(bytes(i + 3)) << 24
        i += 4
        x13 = (bytes(i) And &HFFUI) Or (bytes(i + 1) And &HFFUI) << 8 Or (bytes(i + 2) And &HFFUI) << 16 Or CUInt(bytes(i + 3)) << 24
        i += 4
        x14 = (bytes(i) And &HFFUI) Or (bytes(i + 1) And &HFFUI) << 8 Or (bytes(i + 2) And &HFFUI) << 16 Or CUInt(bytes(i + 3)) << 24
        i += 4
        x15 = (bytes(i) And &HFFUI) Or (bytes(i + 1) And &HFFUI) << 8 Or (bytes(i + 2) And &HFFUI) << 16 Or CUInt(bytes(i + 3)) << 24

        Dim aa, bb, cc, dd As UInteger

        aa = a
        bb = b
        cc = c
        dd = d

        aa += ((bb And cc) Or ((Not bb) And dd)) + x0
        aa = aa << 3 Or aa >> -3
        dd += ((aa And bb) Or ((Not aa) And cc)) + x1
        dd = dd << 7 Or dd >> -7
        cc += ((dd And aa) Or ((Not dd) And bb)) + x2
        cc = cc << 11 Or cc >> -11
        bb += ((cc And dd) Or ((Not cc) And aa)) + x3
        bb = bb << 19 Or bb >> -19
        aa += ((bb And cc) Or ((Not bb) And dd)) + x4
        aa = aa << 3 Or aa >> -3
        dd += ((aa And bb) Or ((Not aa) And cc)) + x5
        dd = dd << 7 Or dd >> -7
        cc += ((dd And aa) Or ((Not dd) And bb)) + x6
        cc = cc << 11 Or cc >> -11
        bb += ((cc And dd) Or ((Not cc) And aa)) + x7
        bb = bb << 19 Or bb >> -19
        aa += ((bb And cc) Or ((Not bb) And dd)) + x8
        aa = aa << 3 Or aa >> -3
        dd += ((aa And bb) Or ((Not aa) And cc)) + x9
        dd = dd << 7 Or dd >> -7
        cc += ((dd And aa) Or ((Not dd) And bb)) + x10
        cc = cc << 11 Or cc >> -11
        bb += ((cc And dd) Or ((Not cc) And aa)) + x11
        bb = bb << 19 Or bb >> -19
        aa += ((bb And cc) Or ((Not bb) And dd)) + x12
        aa = aa << 3 Or aa >> -3
        dd += ((aa And bb) Or ((Not aa) And cc)) + x13
        dd = dd << 7 Or dd >> -7
        cc += ((dd And aa) Or ((Not dd) And bb)) + x14
        cc = cc << 11 Or cc >> -11
        bb += ((cc And dd) Or ((Not cc) And aa)) + x15
        bb = bb << 19 Or bb >> -19

        aa += ((bb And (cc Or dd)) Or (cc And dd)) + x0 + &H5A827999UI
        aa = aa << 3 Or aa >> -3
        dd += ((aa And (bb Or cc)) Or (bb And cc)) + x4 + &H5A827999UI
        dd = dd << 5 Or dd >> -5
        cc += ((dd And (aa Or bb)) Or (aa And bb)) + x8 + &H5A827999UI
        cc = cc << 9 Or cc >> -9
        bb += ((cc And (dd Or aa)) Or (dd And aa)) + x12 + &H5A827999UI
        bb = bb << 13 Or bb >> -13
        aa += ((bb And (cc Or dd)) Or (cc And dd)) + x1 + &H5A827999UI
        aa = aa << 3 Or aa >> -3
        dd += ((aa And (bb Or cc)) Or (bb And cc)) + x5 + &H5A827999UI
        dd = dd << 5 Or dd >> -5
        cc += ((dd And (aa Or bb)) Or (aa And bb)) + x9 + &H5A827999UI
        cc = cc << 9 Or cc >> -9
        bb += ((cc And (dd Or aa)) Or (dd And aa)) + x13 + &H5A827999UI
        bb = bb << 13 Or bb >> -13
        aa += ((bb And (cc Or dd)) Or (cc And dd)) + x2 + &H5A827999UI
        aa = aa << 3 Or aa >> -3
        dd += ((aa And (bb Or cc)) Or (bb And cc)) + x6 + &H5A827999UI
        dd = dd << 5 Or dd >> -5
        cc += ((dd And (aa Or bb)) Or (aa And bb)) + x10 + &H5A827999UI
        cc = cc << 9 Or cc >> -9
        bb += ((cc And (dd Or aa)) Or (dd And aa)) + x14 + &H5A827999UI
        bb = bb << 13 Or bb >> -13
        aa += ((bb And (cc Or dd)) Or (cc And dd)) + x3 + &H5A827999UI
        aa = aa << 3 Or aa >> -3
        dd += ((aa And (bb Or cc)) Or (bb And cc)) + x7 + &H5A827999UI
        dd = dd << 5 Or dd >> -5
        cc += ((dd And (aa Or bb)) Or (aa And bb)) + x11 + &H5A827999UI
        cc = cc << 9 Or cc >> -9
        bb += ((cc And (dd Or aa)) Or (dd And aa)) + x15 + &H5A827999UI
        bb = bb << 13 Or bb >> -13

        aa += (bb Xor cc Xor dd) + x0 + &H6ED9EBA1UI
        aa = aa << 3 Or aa >> -3
        dd += (aa Xor bb Xor cc) + x8 + &H6ED9EBA1UI
        dd = dd << 9 Or dd >> -9
        cc += (dd Xor aa Xor bb) + x4 + &H6ED9EBA1UI
        cc = cc << 11 Or cc >> -11
        bb += (cc Xor dd Xor aa) + x12 + &H6ED9EBA1UI
        bb = bb << 15 Or bb >> -15
        aa += (bb Xor cc Xor dd) + x2 + &H6ED9EBA1UI
        aa = aa << 3 Or aa >> -3
        dd += (aa Xor bb Xor cc) + x10 + &H6ED9EBA1UI
        dd = dd << 9 Or dd >> -9
        cc += (dd Xor aa Xor bb) + x6 + &H6ED9EBA1UI
        cc = cc << 11 Or cc >> -11
        bb += (cc Xor dd Xor aa) + x14 + &H6ED9EBA1UI
        bb = bb << 15 Or bb >> -15
        aa += (bb Xor cc Xor dd) + x1 + &H6ED9EBA1UI
        aa = aa << 3 Or aa >> -3
        dd += (aa Xor bb Xor cc) + x9 + &H6ED9EBA1UI
        dd = dd << 9 Or dd >> -9
        cc += (dd Xor aa Xor bb) + x5 + &H6ED9EBA1UI
        cc = cc << 11 Or cc >> -11
        bb += (cc Xor dd Xor aa) + x13 + &H6ED9EBA1UI
        bb = bb << 15 Or bb >> -15
        aa += (bb Xor cc Xor dd) + x3 + &H6ED9EBA1UI
        aa = aa << 3 Or aa >> -3
        dd += (aa Xor bb Xor cc) + x11 + &H6ED9EBA1UI
        dd = dd << 9 Or dd >> -9
        cc += (dd Xor aa Xor bb) + x7 + &H6ED9EBA1UI
        cc = cc << 11 Or cc >> -11
        bb += (cc Xor dd Xor aa) + x15 + &H6ED9EBA1UI
        bb = bb << 15 Or bb >> -15

        a += aa
        b += bb
        c += cc
        d += dd
    End Sub
 
Last edited:
I just thought I'd check my results with a big file. Looks like the code in the link PlausiblyDamp gave chokes with big files. Mine can chug through a 330MB file in 10secs on a slowish laptop, I gave up on the other program after a minute or two.

A smaller file took mine 50ms, took the other >6000ms. I guess the difference is that I'm not using arrays (so the UIntegers are all on the stack), calling out to methods, or changing Types. The results tallied.
 

Attachments

Thanks jo0ls,
your code works very good.

But I've found two issues:
The first is that of a byte is 0 it is converted to hex as "0" which should be "00".
(Nothing hard to fix I guess)

The second more serious one is that it only works when calling update with the complete bytearray, otherwise it computes a wrong MD4 hash.

Visual Basic:
bytes = My.Computer.FileSystem.ReadAllBytes(FN)
md4.Update(bytes)
'Computes:        A62CAB5A7F6C5F23AC580B4B82FD86D
'(Which should be A62CAB5A7F6C5F23AC5800B4B82FD86D)
And
Visual Basic:
Dim b(1024 * 1024) As Byte
Dim FStream As New IO.FileStream(FN, IO.FileMode.Open)
While FStream.Read(b, 0, b.Length)
    md4.Update(b, 0, b.Length)
End While
'Computes: 54EA4FD5B459DC7347645EB386BA3512
 
Never mind, my own stupid error.

It's
Visual Basic:
Dim NumRead As Integer = FStream.Read(b, 0, b.Length)
While NumRead <> 0
    MD4.Update(b, 0, NumRead)
    NumRead = FStream.Read(b, 0, b.Length)
End While
 
To pad the bytes in the hex string you can use:

Dim sb As New System.Text.StringBuilder
For Each b As Byte In result
sb.Append(Convert.ToString(b, 16).PadLeft(2, "0"c).ToUpper)
Next
 
Back
Top