MD5 Message-Digest Algorithm

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
Aacini
Expert
Posts: 1885
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: MD5 Message-Digest Algorithm

#16 Post by Aacini » 10 May 2014 10:55

Magialisk wrote:... If you add two binary numbers it doesn't matter whether the MSB "represents" a sign bit or not, the operation will carry out the same and any carry will be thrown away, hence the mod2^32 result. At least that's what I convinced myself after running my subroutine tests and eventually finding my bug elsewhere :)


Yes, this is true. As a matter of fact, in the CPU op-codes (assembly language instructions) there are unsigned multiplication/division operations (MUL/DIV) separated from signed ones (IMUL/IDIV) because in this case the result is different, but there are not separated signed/unsigned add/subtract operations!

Antonio

PS - I think all your code will run slightly faster if you eliminate all not needed delayed expansions in SET /A instructions; for example, instead of:

Code: Select all

result = !DigA'! + !DigB'! + !Radians[%%i]!


you should write:

Code: Select all

result = DigA' + DigB' + Radians[%%i]

penpen
Expert
Posts: 1988
Joined: 23 Jun 2013 06:15
Location: Germany

Re: MD5 Message-Digest Algorithm

#17 Post by penpen » 10 May 2014 12:29

Aacini wrote:PS - I think all your code will run slightly faster if you eliminate all not needed delayed expansions in SET /A instructions; for example, instead of:

Code: Select all

result = !DigA'! + !DigB'! + !Radians[%%i]!


you should write:

Code: Select all

result = DigA' + DigB' + Radians[%%i]

There is another benefit:

Code: Select all

set A=%B%
may result in the error "overflow detected" when B equals -2147483648:
See http://www.dostips.com/forum/viewtopic.php?f=3&t=3758.
While the other version should run error free, but you better test it (on my xp both works).
(I've currently not watched for other possible issues.)

penpen

carlos
Expert
Posts: 503
Joined: 20 Aug 2010 13:57
Location: Chile
Contact:

Re: MD5 Message-Digest Algorithm

#18 Post by carlos » 10 May 2014 13:41

I found this:

Code: Select all

http://stackoverflow.com/questions/13224273/difference-between-signed-and-unsigned-on-bitwise-operations


it list the operations that are irrelevants using signed or unsigned.
Look that right shift should be on unsigned.
But in the code of einstein, the right shift is in a signed number: (? & 0x7FFFFFFF)
Edit: I found this on a msdn article:
Right Shifts
The right-shift operator causes the bit pattern in shift-expression to be shifted to the right by the number of positions specified by additive-expression. For unsigned numbers, the bit positions that have been vacated by the shift operation are zero-filled. For signed numbers, the sign bit is used to fill the vacated bit positions. In other words, if the number is positive, 0 is used, and if the number is negative, 1 is used.
Important note Important: The result of a right-shift of a signed negative number is implementation-dependent. Although Visual C++ uses the sign bit to fill vacated bit positions, there is no guarantee that other implementations also do so.



Also, I think that einstein code should be work more speedy, if they remove all the set /a. Left it like a one line set /a
First construct it like macro.

Example:

Code: Select all

set "md5=? = A + ( B & C | ~B & D ) + 0xd76aa478 + M_0 "
set "md5=!md5!, A = B + ( (? <<  7) | ((? & 0x7FFFFFFF) >> 25) ) + ( ?>>31 & 0x40 )"
set "md5=!md5!, ? = A + ( B & C | ~B & D ) + 0xd76aa478 + M_0"
rem ...
and then:
set /a "%md5%"
Last edited by carlos on 10 May 2014 15:35, edited 3 times in total.

einstein1969
Expert
Posts: 941
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: MD5 Message-Digest Algorithm

#19 Post by einstein1969 » 10 May 2014 14:03

@penpen

Thanks for

Code: Select all

set /a A=%B%


I have same error on windows 7 32bit.

I have done tests and seems that the code work well, nevertheless.

@Magialisk
I have rewritten the intermediary code for improve understanding. I'm not very good at explaining how does Antonio :) . In general, I expect questions from others ...

This is the precedent version that I develop and can be used in the original main without modification (I hope...)

This version is fast and small. Can be used in a macro , but this is next step.

Includes a progress indicator with speed in Bytes/s. The overhead is minimal. If not necessary is possible remove only that part that begin with

Code: Select all

::progress
......

(It does not create problem if it is removed)


Code: Select all

(
:do_md5
setlocal

set block=%~1

:: Break the input block into sixteen 32-bit words
set "A=0" & (For /L %%a in (120,-8,0) DO set /a M_!A!=0x!block:~%%a,8!, A+=1) & set block=


:: Initialize this chunk's digest to the running digest value. Initialize Shift-Rotate(S) value
set /a A=!digA0!, B=!digB0!, C=!digC0!, D=!digD0!, S=2

:: Round 1
:: F = (b & c) | ((~b) & d).  Wikipedia report F=D xor (B and (C xor D)) faster, but in Dos Set seems slower.
:: Shift-Rotate(S): 7 12 17 22 . Replace variable X with ?

FOR /L %%i IN (0,1,15) DO set /a "S=(S-2) %% 20 +7, ?=A + (B & C | ~B & D) + !Radians[%%i]! + M_%%i, A=D, D=C, C=B, B+=((? << S) | ((? & 0x7FFFFFFF) >> (32-S)))+( (?>>31) & (1<< (S-1)) )"

:: Round 2
:: G = (B & D) | (C & (~D) )
:: Shift-Rotate 5 9 14 20

FOR /L %%i IN (16,1,31) DO (
   set /a "S=(%%i %% 4+2)*(%%i %% 4+5)/2, g=(5*%%i+1)%%16"
   set /a "?=A + (B & D | C & ~D) + !Radians[%%i]! + M_!g!, A=D, D=C, C=B, B+=((? << S) | ((? & 0x7FFFFFFF) >> (32-S)))+( (?>>31) & (1<< (S-1)) )"
)

:: Round 3
:: 4, 11, 16, 23
:: H = b ^ c ^ d

FOR /L %%i IN (32,1,47) DO (
   set /a "S=4+%%i %% 2*7+12*(%%i>>1&1), g=(3*%%i+5)%%16"
   set /a "?=A+(B ^^ C ^^ D)+!Radians[%%i]!+M_!g!, A=D, D=C, C=B, B+=((? << S) | ((? & 0x7FFFFFFF) >> (32-S)))+( (?>>31) & (1<< (S-1)) )"
)

:: Round 4
:: 6, 10, 15, 21
:: I = c ^ (b | (~d))

FOR /L %%i IN (48,1,63) DO (
   set /a "S=(%%i %% 4+2)*(%%i %% 4+5)/2+1, g=(7*%%i)%%16"
   set /a "?=A+(C ^^ (B | ~D))+!Radians[%%i]!+M_!g!, A=D, D=C, C=B, B+=((? << S) | ((? & 0x7FFFFFFF) >> (32-S)))+( (?>>31) & (1<< (S-1)) )"
)

)

:: Add this chunk's result to the running digest value
(endlocal & set /a digA0+=%A%, digB0+=%B%, digC0+=%C%, digD0+=%D%)

::performance    i ~ Bytes committed
if "!i:~-2!"=="00" (
  if not defined t0 (
    for /f %%a in ('copy /Z "%~f0" nul') do set "_CR=%%a"
    set t0=!time!
  ) else (
    set "t1=!time!"
    for /F "tokens=1-8 delims=:.," %%a in ("!t0: =0!:!t1: =0!") do set /a "A=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, A+=(A>>31) & 8640000, _Bytes=i-1600-64, _Bytes+=64, _Bytes_s=_Bytes*100/A"
    <nul set/p"=Bytes: !i!  -  Bytes/s: !_Bytes_s!   !_CR!"
    set _Bytes_s=
    set _Bytes=
    set t1=
  )
)

exit /b


I'm working on the next version. I have touched the 2000Bytes/s !
This is the average speed for the part that is measured with the code above (::Performance)

There are modification to do in the main for reduce the env for achieve this speed.

I think that you can still squeeze enough! :D (My goal is 4096Byte/s :shock: )

Edit: I have seen now Carlos's replay:
@Carlos
Thanks, I have read. The part of code that you have signed is the patch for the Shift Rotate Left. In this part I have included an IF for negative number (ie number with bit number 31 at 1) is this part:" ?>>31 & " it is equivalent at IF !?! lss 0 .....
May look the Antonio's post.

And for the Set /a with a one line is the same that i came to do for achieve higher performace. Thanks for the TipS! :)

einstein1969

carlos
Expert
Posts: 503
Joined: 20 Aug 2010 13:57
Location: Chile
Contact:

Re: MD5 Message-Digest Algorithm

#20 Post by carlos » 10 May 2014 15:09

I think you only can merge the s:

Code: Select all

set /a "g=(5*%%i+1)%%16"
set /a "?=A + (B & D | C & ~D) + !Radians[%%i]! + M_!g!, A=D, D=C, C=B, B+=((? << (S=(%%i %% 4+2)*(%%i %% 4+5)/2)) | ((? & 0x7FFFFFFF) >> (32-S)))+( (?>>31) & (1<< (S-1)) )"


but test the performance. I'm not sure if this:

Code: Select all

set /a a=1+(b=2)

is more speedy than:

Code: Select all

set /a b=2,a=1+b


But the last is more readable. Your current code is readable. Not sacrifice readability for gain 0,1 ms.

einstein1969
Expert
Posts: 941
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: MD5 Message-Digest Algorithm

#21 Post by einstein1969 » 10 May 2014 16:02

carlos wrote:I think you only can merge the s:

Code: Select all

set /a "g=(5*%%i+1)%%16"
set /a "?=A + (B & D | C & ~D) + !Radians[%%i]! + M_!g!, A=D, D=C, C=B, B+=((? << (S=(%%i %% 4+2)*(%%i %% 4+5)/2)) | ((? & 0x7FFFFFFF) >> (32-S)))+( (?>>31) & (1<< (S-1)) )"


but test the performance. I'm not sure if this:

Code: Select all

set /a a=1+(b=2)

is more speedy than:

Code: Select all

set /a b=2,a=1+b


But the last is more readable. Your current code is readable. Not sacrifice readability for gain 0,1 ms.


I have tested in separate env (empty)

set /a a=1+(b=2) about 29,3 microsec
set /a b=2,a=1+b '' 30,6 microsec

129 microsec.

Code: Select all

 set /a "g=(5*%%?+1)%%16"
 set /a "?=A + (B & D | C & ~D) + 55 + 44, A=D, D=C, C=B, B+=((? << (S=(%%? %% 4+2)*(%%? %% 4+5)/2)) | ((? & 0x7FFFFFFF) >> (32-S)))+( (?>>31) & (1<< (S-1)) )"


133 microsec

Code: Select all

 set /a "S=(%%? %% 4+2)*(%%? %% 4+5)/2, g=(5*%%?+1)%%16"
 set /a "?=A + (B & D | C & ~D) + 55 + 44, A=D, D=C, C=B, B+=((? << S) | ((? & 0x7FFFFFFF) >> (32-S)))+( (?>>31) & (1<< (S-1)) )"


this is repeted 64 times * Number of total byte / 64 = Number of total byte .
On 100000 byte is 100000*(133-129) microsec = 0,4 sec :roll:

Edit : I have touch 3000Bytes/s :)


einstein1969

einstein1969
Expert
Posts: 941
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: MD5 Message-Digest Algorithm

#22 Post by einstein1969 » 11 May 2014 14:57

Hi Magialisk,

This is the version that is expand for better performance.

I have leaved some comment and legibility at the expense of performance.

of course you can still optimize. My goal is now 8000Bytes/s :shock:

Code: Select all

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: Rif: http://www.dostips.com/forum/viewtopic.php?p=34174#p34174
::      http://en.wikipedia.org/wiki/MD5
::      http://www.ietf.org/rfc/rfc1321.txt
::      http://www.openbsd.org/cgi-bin/cvsweb/src/sys/crypto/md5.c
::     
:: To increase performance you can merge two or more lines of SET /A into one and/or create macro to move in Main
::
:: Master Formula example:
:: %_F_% = (B AND C) OR ((NOT B) AND D) = (B & C) | ((~B) & D)
:: Rotate-Shift = S :
:: => X = A + %_F_% + Radians_0 + M_0
:: => A = B + ( (X << S) | ( (X & 0x7FFFFFFF) >> (32-S) ) + ( (X >> 31) & ( 1 << (S-1) ) )"
::
::
:do_md5_fast
(setlocal & set "block=" & set b=%~1

:: Break the input block into sixteen 32-bit words
set "A=0" & For /L %%a in (120,-8,0) DO set /a M_!A!=0x!b:~%%a,8!, A+=1

:: Initialize this chunk's digest to the running digest value
set /a A=!digA0!, B=!digB0!, C=!digC0!, D=!digD0!

:: Round 1  -  Shift-Rot.: 7, 12, 17, 22.   F = (b & c) | ((~b) & d)
set /a "? = A + ( B & C | ~B & D ) + 0xd76aa478 + M_0 , A = B + ( ? <<  7 | (? & 0x7FFFFFFF) >> 25 ) + (?>>31 & 0x40)"
set /a "? = D + ( A & B | ~A & C ) + 0xe8c7b756 + M_1 , D = A + ( ? << 12 | (? & 0x7FFFFFFF) >> 20 ) + (?>>31 & 0x800)"
set /a "? = C + ( D & A | ~D & B ) + 0x242070db + M_2 , C = D + ( ? << 17 | (? & 0x7FFFFFFF) >> 15 ) + (?>>31 & 0x10000)"
set /a "? = B + ( C & D | ~C & A ) + 0xc1bdceee + M_3 , B = C + ( ? << 22 | (? & 0x7FFFFFFF) >> 10 ) + (?>>31 & 0x200000)"
set /a "? = A + ( B & C | ~B & D ) + 0xf57c0faf + M_4 , A = B + ( ? <<  7 | (? & 0x7FFFFFFF) >> 25 ) + (?>>31 & 0x40)"
set /a "? = D + ( A & B | ~A & C ) + 0x4787c62a + M_5 , D = A + ( ? << 12 | (? & 0x7FFFFFFF) >> 20 ) + (?>>31 & 0x800)"
set /a "? = C + ( D & A | ~D & B ) + 0xa8304613 + M_6 , C = D + ( ? << 17 | (? & 0x7FFFFFFF) >> 15 ) + (?>>31 & 0x10000)"
set /a "? = B + ( C & D | ~C & A ) + 0xfd469501 + M_7 , B = C + ( ? << 22 | (? & 0x7FFFFFFF) >> 10 ) + (?>>31 & 0x200000)"
set /a "? = A + ( B & C | ~B & D ) + 0x698098d8 + M_8 , A = B + ( ? <<  7 | (? & 0x7FFFFFFF) >> 25 ) + (?>>31 & 0x40)"
set /a "? = D + ( A & B | ~A & C ) + 0x8b44f7af + M_9 , D = A + ( ? << 12 | (? & 0x7FFFFFFF) >> 20 ) + (?>>31 & 0x800)"
set /a "? = C + ( D & A | ~D & B ) + 0xffff5bb1 + M_10, C = D + ( ? << 17 | (? & 0x7FFFFFFF) >> 15 ) + (?>>31 & 0x10000)"
set /a "? = B + ( C & D | ~C & A ) + 0x895cd7be + M_11, B = C + ( ? << 22 | (? & 0x7FFFFFFF) >> 10 ) + (?>>31 & 0x200000)"
set /a "? = A + ( B & C | ~B & D ) + 0x6b901122 + M_12, A = B + ( ? <<  7 | (? & 0x7FFFFFFF) >> 25 ) + (?>>31 & 0x40)"
set /a "? = D + ( A & B | ~A & C ) + 0xfd987193 + M_13, D = A + ( ? << 12 | (? & 0x7FFFFFFF) >> 20 ) + (?>>31 & 0x800)"
set /a "? = C + ( D & A | ~D & B ) + 0xa679438e + M_14, C = D + ( ? << 17 | (? & 0x7FFFFFFF) >> 15 ) + (?>>31 & 0x10000)"
set /a "? = B + ( C & D | ~C & A ) + 0x49b40821 + M_15, B = C + ( ? << 22 | (? & 0x7FFFFFFF) >> 10 ) + (?>>31 & 0x200000)"

:: Round 2  -  Shift-Rot.: 5, 9, 14, 20.    G = (B & D) | (C & (~D) )
set /a "? = A + ( B & D | C & ~D ) + 0xf61e2562 + M_1 , A = B + ( ? <<  5 | (? & 0x7FFFFFFF) >> 27 ) + (?>>31 & 0x10)"
set /a "? = D + ( A & C | B & ~C ) + 0xc040b340 + M_6 , D = A + ( ? <<  9 | (? & 0x7FFFFFFF) >> 23 ) + (?>>31 & 0x100)"
set /a "? = C + ( D & B | A & ~B ) + 0x265e5a51 + M_11, C = D + ( ? << 14 | (? & 0x7FFFFFFF) >> 18 ) + (?>>31 & 0x2000)"
set /a "? = B + ( C & A | D & ~A ) + 0xe9b6c7aa + M_0 , B = C + ( ? << 20 | (? & 0x7FFFFFFF) >> 12 ) + (?>>31 & 0x80000)"
set /a "? = A + ( B & D | C & ~D ) + 0xd62f105d + M_5 , A = B + ( ? <<  5 | (? & 0x7FFFFFFF) >> 27 ) + (?>>31 & 0x10)"
set /a "? = D + ( A & C | B & ~C ) + 0x02441453 + M_10, D = A + ( ? <<  9 | (? & 0x7FFFFFFF) >> 23 ) + (?>>31 & 0x100)"
set /a "? = C + ( D & B | A & ~B ) + 0xd8a1e681 + M_15, C = D + ( ? << 14 | (? & 0x7FFFFFFF) >> 18 ) + (?>>31 & 0x2000)"
set /a "? = B + ( C & A | D & ~A ) + 0xe7d3fbc8 + M_4 , B = C + ( ? << 20 | (? & 0x7FFFFFFF) >> 12 ) + (?>>31 & 0x80000)"
set /a "? = A + ( B & D | C & ~D ) + 0x21e1cde6 + M_9 , A = B + ( ? <<  5 | (? & 0x7FFFFFFF) >> 27 ) + (?>>31 & 0x10)"
set /a "? = D + ( A & C | B & ~C ) + 0xc33707d6 + M_14, D = A + ( ? <<  9 | (? & 0x7FFFFFFF) >> 23 ) + (?>>31 & 0x100)"
set /a "? = C + ( D & B | A & ~B ) + 0xf4d50d87 + M_3 , C = D + ( ? << 14 | (? & 0x7FFFFFFF) >> 18 ) + (?>>31 & 0x2000)"
set /a "? = B + ( C & A | D & ~A ) + 0x455a14ed + M_8 , B = C + ( ? << 20 | (? & 0x7FFFFFFF) >> 12 ) + (?>>31 & 0x80000)"
set /a "? = A + ( B & D | C & ~D ) + 0xa9e3e905 + M_13, A = B + ( ? <<  5 | (? & 0x7FFFFFFF) >> 27 ) + (?>>31 & 0x10)"
set /a "? = D + ( A & C | B & ~C ) + 0xfcefa3f8 + M_2 , D = A + ( ? <<  9 | (? & 0x7FFFFFFF) >> 23 ) + (?>>31 & 0x100)"
set /a "? = C + ( D & B | A & ~B ) + 0x676f02d9 + M_7 , C = D + ( ? << 14 | (? & 0x7FFFFFFF) >> 18 ) + (?>>31 & 0x2000)"
set /a "? = B + ( C & A | D & ~A ) + 0x8d2a4c8a + M_12, B = C + ( ? << 20 | (? & 0x7FFFFFFF) >> 12 ) + (?>>31 & 0x80000)"

:: Round 3  -  Shift-Rot.: 4, 11, 16, 23.   H = b xor c xor d
set /a "? = A + ( B ^ C ^ D ) + 0xfffa3942 + M_5 , A = B + ( ? <<  4 | (? & 0x7FFFFFFF) >> 28 ) + (?>>31 & 0x8)"
set /a "? = D + ( A ^ B ^ C ) + 0x8771f681 + M_8 , D = A + ( ? << 11 | (? & 0x7FFFFFFF) >> 21 ) + (?>>31 & 0x400)"
set /a "? = C + ( D ^ A ^ B ) + 0x6d9d6122 + M_11, C = D + ( ? << 16 | (? & 0x7FFFFFFF) >> 16 ) + (?>>31 & 0x8000)"
set /a "? = B + ( C ^ D ^ A ) + 0xfde5380c + M_14, B = C + ( ? << 23 | (? & 0x7FFFFFFF) >>  9 ) + (?>>31 & 0x400000)"
set /a "? = A + ( B ^ C ^ D ) + 0xa4beea44 + M_1 , A = B + ( ? <<  4 | (? & 0x7FFFFFFF) >> 28 ) + (?>>31 & 0x8)"
set /a "? = D + ( A ^ B ^ C ) + 0x4bdecfa9 + M_4 , D = A + ( ? << 11 | (? & 0x7FFFFFFF) >> 21 ) + (?>>31 & 0x400)"
set /a "? = C + ( D ^ A ^ B ) + 0xf6bb4b60 + M_7 , C = D + ( ? << 16 | (? & 0x7FFFFFFF) >> 16 ) + (?>>31 & 0x8000)"
set /a "? = B + ( C ^ D ^ A ) + 0xbebfbc70 + M_10, B = C + ( ? << 23 | (? & 0x7FFFFFFF) >>  9 ) + (?>>31 & 0x400000)"
set /a "? = A + ( B ^ C ^ D ) + 0x289b7ec6 + M_13, A = B + ( ? <<  4 | (? & 0x7FFFFFFF) >> 28 ) + (?>>31 & 0x8)"
set /a "? = D + ( A ^ B ^ C ) + 0xeaa127fa + M_0 , D = A + ( ? << 11 | (? & 0x7FFFFFFF) >> 21 ) + (?>>31 & 0x400)"
set /a "? = C + ( D ^ A ^ B ) + 0xd4ef3085 + M_3 , C = D + ( ? << 16 | (? & 0x7FFFFFFF) >> 16 ) + (?>>31 & 0x8000)"
set /a "? = B + ( C ^ D ^ A ) + 0x04881d05 + M_6 , B = C + ( ? << 23 | (? & 0x7FFFFFFF) >>  9 ) + (?>>31 & 0x400000)"
set /a "? = A + ( B ^ C ^ D ) + 0xd9d4d039 + M_9 , A = B + ( ? <<  4 | (? & 0x7FFFFFFF) >> 28 ) + (?>>31 & 0x8)"
set /a "? = D + ( A ^ B ^ C ) + 0xe6db99e5 + M_12, D = A + ( ? << 11 | (? & 0x7FFFFFFF) >> 21 ) + (?>>31 & 0x400)"
set /a "? = C + ( D ^ A ^ B ) + 0x1fa27cf8 + M_15, C = D + ( ? << 16 | (? & 0x7FFFFFFF) >> 16 ) + (?>>31 & 0x8000)"
set /a "? = B + ( C ^ D ^ A ) + 0xc4ac5665 + M_2 , B = C + ( ? << 23 | (? & 0x7FFFFFFF) >>  9 ) + (?>>31 & 0x400000)"

:: Round 4  -  Shift-Rot.: 6, 10, 15, 21.   I = c xor (b or (not(d)))
set /a "? = A + ( C ^ (B | ~D) ) + 0xf4292244 + M_0 , A = B + ( ? <<  6 | (? & 0x7FFFFFFF) >> 26 ) + (?>>31 & 0x20)"
set /a "? = D + ( B ^ (A | ~C) ) + 0x432aff97 + M_7 , D = A + ( ? << 10 | (? & 0x7FFFFFFF) >> 22 ) + (?>>31 & 0x200)"
set /a "? = C + ( A ^ (D | ~B) ) + 0xab9423a7 + M_14, C = D + ( ? << 15 | (? & 0x7FFFFFFF) >> 17 ) + (?>>31 & 0x4000)"
set /a "? = B + ( D ^ (C | ~A) ) + 0xfc93a039 + M_5 , B = C + ( ? << 21 | (? & 0x7FFFFFFF) >> 11 ) + (?>>31 & 0x100000)"
set /a "? = A + ( C ^ (B | ~D) ) + 0x655b59c3 + M_12, A = B + ( ? <<  6 | (? & 0x7FFFFFFF) >> 26 ) + (?>>31 & 0x20)"
set /a "? = D + ( B ^ (A | ~C) ) + 0x8f0ccc92 + M_3 , D = A + ( ? << 10 | (? & 0x7FFFFFFF) >> 22 ) + (?>>31 & 0x200)"
set /a "? = C + ( A ^ (D | ~B) ) + 0xffeff47d + M_10, C = D + ( ? << 15 | (? & 0x7FFFFFFF) >> 17 ) + (?>>31 & 0x4000)"
set /a "? = B + ( D ^ (C | ~A) ) + 0x85845dd1 + M_1 , B = C + ( ? << 21 | (? & 0x7FFFFFFF) >> 11 ) + (?>>31 & 0x100000)"
set /a "? = A + ( C ^ (B | ~D) ) + 0x6fa87e4f + M_8 , A = B + ( ? <<  6 | (? & 0x7FFFFFFF) >> 26 ) + (?>>31 & 0x20)"
set /a "? = D + ( B ^ (A | ~C) ) + 0xfe2ce6e0 + M_15, D = A + ( ? << 10 | (? & 0x7FFFFFFF) >> 22 ) + (?>>31 & 0x200)"
set /a "? = C + ( A ^ (D | ~B) ) + 0xa3014314 + M_6 , C = D + ( ? << 15 | (? & 0x7FFFFFFF) >> 17 ) + (?>>31 & 0x4000)"
set /a "? = B + ( D ^ (C | ~A) ) + 0x4e0811a1 + M_13, B = C + ( ? << 21 | (? & 0x7FFFFFFF) >> 11 ) + (?>>31 & 0x100000)"
set /a "? = A + ( C ^ (B | ~D) ) + 0xf7537e82 + M_4 , A = B + ( ? <<  6 | (? & 0x7FFFFFFF) >> 26 ) + (?>>31 & 0x20)"
set /a "? = D + ( B ^ (A | ~C) ) + 0xbd3af235 + M_11, D = A + ( ? << 10 | (? & 0x7FFFFFFF) >> 22 ) + (?>>31 & 0x200)"
set /a "? = C + ( A ^ (D | ~B) ) + 0x2ad7d2bb + M_2 , C = D + ( ? << 15 | (? & 0x7FFFFFFF) >> 17 ) + (?>>31 & 0x4000)"
set /a "? = B + ( D ^ (C | ~A) ) + 0xeb86d391 + M_9 , B = C + ( ? << 21 | (? & 0x7FFFFFFF) >> 11 ) + (?>>31 & 0x100000)"
)
(:: Add this chunk's result to the running digest value
endlocal & set /a digA0+=%A%, digB0+=%B%, digC0+=%C%, digD0+=%D%

::performance    i ~ Bytes committed from Main
if "!i:~-2!"=="00" (
  if not defined t0 (
    for /f %%a in ('copy /Z "%~f0" nul') do set "_CR=%%a"
    set t0=!time!
  ) else (
    set "t1=!time!"
    for /F "tokens=1-8 delims=:.," %%a in ("!t0: =0!:!t1: =0!") do set /a "A=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, A+=(A>>31) & 8640000, _Bytes=i-1600, _Bytes_s=_Bytes*100/A"
    <nul set/p"=ti: !time! - Bytes= !i!    Bytes/s: !_Bytes_s!    !_CR!"
    set _Bytes_s=
    set _Bytes=
    set t1=
  )
)
exit /b)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


in my Main i have modified other thing and the speed is about 2900-3100Bytes/s.

But it works even without these changes. It's just slower.

This is the changes in the central part:

Code: Select all

for /F "usebackq skip=1 tokens=1,2 delims=: " %%b in ("%tempFile2%") do (

   IF NOT %%c==no (
      if !i! neq 0x%%b (
         set /A _cb=0x%%b-i
         for /L %%i in (!_cb!,-1,1) do (
            set "block=00!block!"
            set /A "d=(d+1) %% 64"
            if !d! equ 0 (
               CALL:do_md5_fast !block!
               set block=
            )
         )
      )
      set "block=%%c!block!"
      set /A "i=0x%%b+1, d=(d+1) %% 64"
      if !d! equ 0 (
         CALL:do_md5_fast !block!
         set block=
      )
   ) ELSE set emptyfile=true
)


And you can comment the Randians's Table and remove other variable from environment to achieve above performance!


EDIT: I have tested the best cases and even if we reduce the time of subroutine at 0 the performance max is about 4000Bytes/s with only a call followed by (exit/b).
A macro is necessary!

Einstein1969

Post Reply