Jump to content
Xtreme .Net Talk

Recommended Posts

Posted

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:

      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:

        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:

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?

Posted

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 :)

Posted (edited)

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.

 

    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

Edited by jo0ls
Posted

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.

md4.zip

Posted

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.

 

bytes = My.Computer.FileSystem.ReadAllBytes(FN)
md4.Update(bytes)
'Computes:        A62CAB5A7F6C5F23AC580B4B82FD86D
'(Which should be A62CAB5A7F6C5F23AC5800B4B82FD86D)

And

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

Posted

Never mind, my own stupid error.

 

It's

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

Posted

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

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...