Arokh Posted May 20, 2008 Posted May 20, 2008 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? Quote
Administrators PlausiblyDamp Posted May 20, 2008 Administrators Posted May 20, 2008 http://www.lucamauri.com/snippet/snip.aspx?id=16 has already got the hard work done ;) If you are still curious about unsigned shifts I can certainly have a look and see what I can dig up... Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
Arokh Posted May 20, 2008 Author Posted May 20, 2008 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 :) Quote
jo0ls Posted May 21, 2008 Posted May 21, 2008 (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 May 21, 2008 by jo0ls Quote
jo0ls Posted May 21, 2008 Posted May 21, 2008 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 Quote
Arokh Posted May 21, 2008 Author Posted May 21, 2008 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 Quote
Arokh Posted May 21, 2008 Author Posted May 21, 2008 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 Quote
jo0ls Posted May 21, 2008 Posted May 21, 2008 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 Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.