Community discussions

MikroTik App
 
User avatar
TealFrog
just joined
Topic Author
Posts: 23
Joined: Sun Oct 02, 2011 11:56 am

Script MD5 Hash Generator

Mon Jun 18, 2012 8:54 am

A script I created to generate MD5 hashes.
# String message to MD5 Hash
# Creates a MD5 hash from a message string
# Version 1.00, 6/17/2012, Created by TealFrog
# Script tested and developed under MikroTik ROS 5.14 thru 5.17
#
# This software is identified as using and is based on the, "RSA Data Security, 
# Inc. MD5 Message-Digest Algorithm".  This program is a derived work from the RSA Data
# Security, Inc. MD5 Message-Digest Algorithm.
# See http://www.ietf.org/rfc/rfc1321.txt for further information.
#
# The author of this program makes no representations concerning either
# the merchantability of this software or the suitability of this
# software for any particular purpose or non-infringement.
# This program is provided "as is" without express or implied warranty of any kind.
# The author makes no representations or warranties of any kind as to the 
# completeness, accuracy, timeliness, availability, functionality and compliance
# with applicable laws. By using this software you accept the risk that the 
# information may be incomplete or inaccurate or may not meet your needs 
# and requirements. The author shall not be liable for any damages or 
# injury arising out of the use of this program. Use this program at your own risk. 
#
# MD5 has been shown to not be collision resistant, as such MD5 is not suitable 
# for certain applications involving security and/or cryptography, 
# see http://en.wikipedia.org/wiki/Md5 for additional information.
#
# $progName, Name of script, set appropriately
:local progName "StrToMd5"

# $arrMessages, An array containing one ore more string messages to create MD5 hash from 
:local arrMessages ( "ABCDEFGHIJKLMNOPQRSTUVWZYZ",   \
                     "abcedefghijklmnopqrstuvwxyz",  \
                     "The quick brown fox jumps over the lazy dog." )

# $strPrefix, Set to a prefix to add before MD5 hash, set "" for empty
:local strPrefix "0x"

# $strSuffix, Set to a suffix to add after MD5 hash, set "" for empty
:local strSuffix ""

# Set $Debug to 1 for additional output, set to zero to turn off debug
:local Debug 0

# $strHexValues, Used to create hexadecimal output
:local strHexValues "0123456789abcdef"
# To have uppercase hexadecimal A-F use the next line instead of the above
# :local strHexValues "0123456789ABCDEF"

# No futher modification required beyond this point unless customizing script
# Start by defining constant values

# ASCII Table $CharSet[0..127]
:local arrCharSet ( "\00", "\01", "\02", "\03", "\04", "\05", "\06", "\07", \ 
                    "\08", "\09", "\0A", "\0B", "\0C", "\0D", "\0E", "\0F", \ 
                    "\10", "\11", "\12", "\13", "\14", "\15", "\16", "\17", \
                    "\18", "\19", "\1A", "\1B", "\1C", "\1D", "\1E", "\1F", \
                    "\20", "\21", "\22", "\23", "\24", "\25", "\26", "\27", \
                    "\28", "\29", "\2A", "\2B", "\2C", "\2D", "\2E", "\2F", \
                    "\30", "\31", "\32", "\33", "\34", "\35", "\36", "\37", \
                    "\38", "\39", "\3A", "\3B", "\3C", "\3D", "\3E", "\3F", \
                    "\40", "\41", "\42", "\43", "\44", "\45", "\46", "\47", \ 
                    "\48", "\49", "\4A", "\4B", "\4C", "\4D", "\4E", "\4F", \
                    "\50", "\51", "\52", "\53", "\54", "\55", "\56", "\57", \
                    "\58", "\59", "\5A", "\5B", "\5C", "\5D", "\5E", "\5F", \
                    "\60", "\61", "\62", "\63", "\64", "\65", "\66", "\67", \
                    "\68", "\69", "\6A", "\6B", "\6C", "\6D", "\6E", "\6F", \
                    "\70", "\71", "\72", "\73", "\74", "\75", "\76", "\77", \
                    "\78", "\79", "\7A", "\7B", "\7C", "\7D", "\7E", "\7F" ) 

# k[i] = floor(abs(sin(i + 1)) × 4294967296) 
# Or just use the following table $k[0..63]:
:local k ( 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, \
           0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501, \
           0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, \
           0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821, \
           0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, \
           0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8, \
           0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, \
           0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A, \
           0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, \
           0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70, \
           0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, \
           0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665, \
           0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, \
           0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1, \
           0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, \
           0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391 )

:local a 0x67452301 
:local b 0xEFCDAB89
:local c 0x98BADCFE
:local d 0x10325476

:local AA 0x67452301
:local BB 0xEFCDAB89
:local CC 0x98BADCFE
:local DD 0x10325476

:local s1 (  7, 12, 17, 22 )
:local s2 (  5,  9, 14, 20 )
:local s3 (  4, 11, 16, 23 )
:local s4 (  6, 10, 15, 21 )

:local i 0
:local j 0
:local x 0
:local S 0
:local T 0
:local lcv 0
:local tmp1 0

:local arrMd5State {}
:local arrWordArray {}
:local ch ""
:local iByteCount 0
:local iCharVal 3
:local iDec 0
:local iHexDigit 8
:local iMd5State 0
:local lBytePosition 0
:local lMessageLength 0
:local lNumberOfWords 0        
:local lShiftedVal 0
:local lWordArray {}
:local lWordArrLen 0
:local lWordCount 0
:local sHex ""
:local sMd5Hash ""
:local sMd5Output ""
:local strWordArray ""

# Start of main program and message loop
:put "$progName: Running..."
:foreach strMessage in=[ :toarray $arrMessages ] do={
   :put "$progName: Message: $strMessage"
   :set ch ""
   :set lShiftedVal 0
   :set lWordCount 0
   :set iByteCount 0
   :set iCharVal 3
   :set lBytePosition 0
   :set lMessageLength [ :len $strMessage ]
   :set lNumberOfWords ( ( ( ( $lMessageLength + 8 ) / 64 ) + 1 ) * 16 )        
   :set strWordArray ""
   :set arrWordArray {}

# Convert to word array 
   :for i from=1 to=($lNumberOfWords) do={
      :set strWordArray ("0," . $strWordArray)
   }
   :set strWordArray  [ :pick $strWordArray 0 ( [ :len $strWordArray ] - 1 ) ]
   :set arrWordArray [ :toarray $strWordArray ]
   
   :if ( $Debug > 0 ) do={
      :put ("$progName: Message Length: " . $lMessageLength)
      :put ("$progName: Number of Words: " . $lNumberOfWords)
   }
   :while ($iByteCount < $lMessageLength) do={
      :set lWordCount ($iByteCount / 4)
      :set lBytePosition (($iByteCount % 4) * 8)
         :if (($lBytePosition < 0) or ($lBytePosition > 31)) do={
            :error ( "$progName: Error --  Calculating byte position " . \
			       "# $lBytePosition, must be 0 thru 31." )
         }
         :set ch [ :pick $strMessage $iByteCount ]
         :if ( [ :len [ :find $arrCharSet $ch ] ] > 0 ) do={
            :set iCharVal ([ :tonum [ :find $arrCharSet $ch ] ])
         } else={
            :error "$progName: Error -- Input contains undefined ASCII value."
         }
         :if ( $Debug > 0 ) do={
            :put ( "$progName: parsed character \$ch: '$ch' " . \
			     "ASCII value \$iCharVal: $iCharVal" )
         }
         :set lShiftedVal ((($iCharVal) << ($lBytePosition)) | \
		                   (($iCharVal) >> (32-($lBytePosition))))
         :if ($iByteCount = 0) do={
            :set lShiftedVal (([ :tonum $lShiftedVal ] + 0) & 0xFFFFFFFF)
            :set arrWordArray (([ :tonum $lShiftedVal ]), \
			                    [ :pick $arrWordArray 1 [ :len $arrWordArray] ])
         } else={
            :set lShiftedVal (([ :tonum [ :pick $arrWordArray $lWordCount] ] + 0) | \
			                  ([ :tonum $lShiftedVal ] + 0))
            :set lShiftedVal (([ :tonum $lShiftedVal ] + 0) & 0xFFFFFFFF)
            :set arrWordArray  ([ :pick $arrWordArray 0 $lWordCount ], $lShiftedVal, \
               [ :pick $arrWordArray ([ :tonum $lWordCount ] + 1) [ :len $arrWordArray] ])   
         }
         :set iByteCount ( $iByteCount + 1 )
      }
      :set lWordCount ( $iByteCount / 4 )
      :set lBytePosition ( ( $iByteCount % 4 ) * 8 )
      :set lShiftedVal [ :pick $arrWordArray $lWordCount ]
      
      :set lShiftedVal ( ( [ :tonum [ :pick $arrWordArray $lWordCount ] ] + 0 ) | \
                         ( ( 0x80 << $lBytePosition ) | \
				           ( 0x80 >> ( 32 - $lBytePosition ) ) ) ) 
      
      :set arrWordArray  ( ( [ :pick $arrWordArray 0 $lWordCount ]  ),  \
                             [ :tonum $lShiftedVal ], \
                           ( [ :pick $arrWordArray ( [ :tonum $lWordCount ] + 1 ) \
   					    [ :len $arrWordArray ] ] ) ) 
					       
      :set arrWordArray  [ :toarray ( ( [ :pick $arrWordArray 0 ($lNumberOfWords - 2) ] ), \
                                    ( ( ( [ :tonum $lMessageLength ] + 0 ) << 3 ) | \
   							     ( ( [ :tonum $lMessageLength ] + 0 ) >> 29 ) ), \
							        ( ( [ :tonum $lMessageLength ] + 0 )  >> 29 ) ) ]
      :set lWordArray [ :toarray $arrWordArray ]
      :set lWordArrLen ( ( [ :len $lWordArray ] ) - 1 )

### Main Loop ###
      :set tmp1 0
      :set x 0
      :set T 0
      :set S 0
      :set i 0
      :set j 0
      :for lcv from=0 to=( $lWordArrLen ) step=16 do={
         :set a 0x67452301 
         :set b 0xEFCDAB89
         :set c 0x98BADCFE
         :set d 0x10325476
         :set AA [ :tonum $a ]
         :set BB [ :tonum $b ]
         :set CC [ :tonum $c ]
         :set DD [ :tonum $d ]

### Round 1 ### 
         :for i from=0 to=15 do={
            :set x ( [ :tonum [ :pick $lWordArray ( $i & 15 ) ] ] + 0 )
            :set T ( [ :tonum [ :pick $k $i ] ] + 0 )
            :set S ( [ :tonum [ :pick $s1 ( $i & 3 ) ] ] + 0 )
# Next line is an alternate mmethod, instead of the line after it	  
#         :set tmp1 ( ( (($b & $c) | (((($b + 1) * -1)) & $d)) + $a + $T + $x ) & 0xFFFFFFFF )
            :set tmp1 ( ( ( $d ^ ( $b & ( $c ^ $d ) ) ) + $a + $T + $x ) & 0xFFFFFFFF )
            :set tmp1 (((tmp1 << $S ) | (($tmp1 >> (32 - $S)))) & 0xFFFFFFFF)
            :set tmp1 ( ( $tmp1 + $b ) & 0xFFFFFFFF )
            :if ( $Debug > 0 ) do={			
               :put ("$progName: Round 1, Answer \$tmp1: $tmp1") 
            }			   
# Rotate a,b,c,d params positions, e.g. d, a, b, c ... c, d, a, b ... b, c, d, a 
# and a gets new value from tmp1
            :set a ( ( [ :tonum $d ] + 0 ) & 0xFFFFFFFF )
            :set d ( ( [ :tonum $c ] + 0 ) & 0xFFFFFFFF )
            :set c ( ( [ :tonum $b ] + 0 ) & 0xFFFFFFFF )
            :set b ( ( [ :tonum $tmp1 ] + 0 ) & 0xFFFFFFFF )
         }
      
### Round 2 ###
         :set j 1
         :for i from=0 to=15 do={
            :set x ( [ :tonum [ :pick $lWordArray ( ( [ :tonum $j ] + 0 ) & 15 ) ] ] + 0 )
            :set T ( [ :tonum [ :pick $k ( $i + 16 ) ] ] + 0 )
            :set S ( [ :tonum [ :pick $s2 ( $i & 3 ) ] ] + 0 )
            :set tmp1 ( ( ( $c ^ ( $d & ( $b ^ $c ) ) ) + $a + $T + $x ) & 0xFFFFFFFF )
            :set tmp1 (((tmp1 << $S ) | (($tmp1 >> (32 - $S)))) & 0xFFFFFFFF)
            :set tmp1 ( ( $tmp1 + $b ) & 0xFFFFFFFF )
            :if ( $Debug > 0 ) do={			
               :put ("$progName: Round 2, Answer \$tmp1: $tmp1") 
            }			   
# Rotate a,b,c,d param positions, e.g. d, a, b, c ... c, d, a, b ... b, c, d, a
            :set a ( ( [ :tonum $d ] + 0 ) & 0xFFFFFFFF )
            :set d ( ( [ :tonum $c ] + 0 ) & 0xFFFFFFFF )
            :set c ( ( [ :tonum $b ] + 0 ) & 0xFFFFFFFF )
            :set b ( ( [ :tonum $tmp1 ] + 0 ) & 0xFFFFFFFF )
            :set j ( $j + 5 )
         }
         
### Round 3 ###
         :set j 5
         :for i from=0 to=15 do={
            :set x ( [ :tonum [ :pick $lWordArray ( ( [ :tonum $j ] + 0 ) & 15 ) ] ] + 0 )
            :set T ( [ :tonum [ :pick $k ( $i + 32 ) ] ] + 0 )
            :set S ( [ :tonum [ :pick $s3 ( $i & 3 ) ] ] + 0 )
            :set tmp1 ( ( ( $b ^ $c ^ $d ) + $a + $T + $x ) & 0xFFFFFFFF )
            :set tmp1 (((tmp1 << $S ) | (($tmp1 >> (32 - $S)))) & 0xFFFFFFFF)
            :set tmp1 ( ( $tmp1 + $b ) & 0xFFFFFFFF )
            :if ( $Debug > 0 ) do={			
               :put ("$progName: Round 3, Answer \$tmp1: $tmp1") 
            }			   
# Rotate a,b,c,d param positions, e.g. d, a, b, c ... c, d, a, b ... b, c, d, a
            :set a ( ( [ :tonum $d ] + 0) & 0xFFFFFFFF )
            :set d ( ( [ :tonum $c ] + 0) & 0xFFFFFFFF )
            :set c ( ( [ :tonum $b ] + 0) & 0xFFFFFFFF )
            :set b ( ( [ :tonum $tmp1 ] + 0) & 0xFFFFFFFF )
            :set j ( $j + 3 )
         }
         
### Round 4 ###
         :set j 0
         :for i from=0 to=15 do={
            :set x ( [ :tonum [ :pick $lWordArray ( ( [ :tonum $j ] + 0 ) & 15 ) ] ] + 0 )
            :set T ( [ :tonum [ :pick $k ( $i + 48 ) ] ] + 0 )
            :set S ( [ :tonum [ :pick $s4 ( $i & 3 ) ] ] + 0 )
# Next line is alternate method to the line following	  
#         :set tmp1 ( $c ^ ( $b | ( ( $d & 0xFFFFFFFF ) ^ 0xFFFFFFFF ) ) )
            :set tmp1 ( ( $c ^ ( $b | ( -1 * ( $d + 1 ) ) ) ) & 0xFFFFFFFF )
            :set tmp1 ( ( $tmp1 + $a + $T + $x ) & 0xFFFFFFFF )
            :set tmp1 ( ((tmp1 << $S ) | (($tmp1 >> (32 - $S)))) & 0xFFFFFFFF )
            :set tmp1 ( ( $tmp1 + $b ) & 0xFFFFFFFF )
            :if ( $Debug > 0 ) do={			
               :put ("$progName: Round 4, Answer \$tmp1: $tmp1") 
            }			   
# Rotate a,b,c,d param positions, e.g. d, a, b, c ... c, d, a, b ... b, c, d, a
            :set a ( ( [ :tonum $d ] + 0) & 0xFFFFFFFF )
            :set d ( ( [ :tonum $c ] + 0) & 0xFFFFFFFF )
            :set c ( ( [ :tonum $b ] + 0) & 0xFFFFFFFF )
            :set b ( ( [ :tonum $tmp1 ] + 0) & 0xFFFFFFFF )
            :set j ( $j + 7 )
         }      
         :set a ( ( $a + $AA ) & 0xFFFFFFFF )    
         :set b ( ( $b + $BB ) & 0xFFFFFFFF )    
         :set c ( ( $c + $CC ) & 0xFFFFFFFF )    
         :set d ( ( $d + $DD ) & 0xFFFFFFFF )    
      }
      :set arrMd5State [ :toarray "$a, $b, $c, $d" ]
      :set sMd5Hash ""
      :set sMd5Output ""
      :set iDec 0
      :set iMd5State 0
      :set sHex ""
      :for i from=0 to=3 do={
         :set iMd5State [ :pick $arrMd5State $i ] 	  
         :for j from=0 to=3 do={
	        :set iMd5State ( [ :tonum $iMd5State ] & 0xFFFFFFFF )
            :if ( $j < 1 ) do={
               :set iDec ( [ :tonum $iMd5State ] & 255 )
            } else={
		       :set iDec ( ( $iMd5State & 0x7FFFFFFE ) / ( 2 << ( ( $j * 8 ) - 1 ) ) )
   		    :if ( ( $iMd5State & 0x80000000 ) > 0 ) do={
	              :set iDec ( $iDec | ( 0x40000000 /  ( 2 << ( ( $j * 8 ) - 2 ) ) ) )
 	           }
   		       :set iDec ( $iDec & 0xFF ) 
            }
   	        :set sHex ""
            :for k from=0 to=( 4 * ( $iHexDigit - 1 ) ) step=4 do={
               :set sHex ( [ :pick [ :tostr $strHexValues ] \
			             ( ( $iDec >> $k ) & 0xF ) \ 
						 ( ( ( $iDec >> $k ) & 0xF ) + 1 ) ] . $sHex ) 
            }
   	        :set sHex [ :tostr $sHex ]
	        :set sHex [ :pick $sHex ( [ :len $sHex ] - 2 ) [ :len $sHex ] ]
            :set sMd5Output ( $sMd5Output . $sHex )	  
         }
   }
# Modify next line to customize MD5 output string	  
   :put ( [ :tostr $strPrefix ] . [ :tostr $sMd5Output ] . [ :tostr $strSuffix ] )
}
:put "$progName: Done."
 
User avatar
boen_robot
Forum Guru
Forum Guru
Posts: 2400
Joined: Thu Aug 31, 2006 4:43 pm
Location: europe://Bulgaria/Plovdiv

Re: Script MD5 Hash Generator

Mon Jun 18, 2012 1:15 pm

One silly question if I may... why? Is there at least one use case for this?
 
User avatar
TealFrog
just joined
Topic Author
Posts: 23
Joined: Sun Oct 02, 2011 11:56 am

Re: Script MD5 Hash Generator

Tue Jun 19, 2012 2:13 am

Admittedly, the script by itself "as-is", is almost useless. It is really meant to fill a niche and be used as a solution to be incorporated into other scripts with the MD5 hash acting as either input to or output from another program or script.

For those who are unaware, MD5, as well as other hashes, can be used to check integrity, create signatures and/or for authentication purposes. Specifically, hashes, i.e. MD5, can be used to check file integrity and/or to create/store a salted password/passphrase. As noted in the scripts comments, MD5 has been determined to be insecure, so if given a choice I would use a different hash algorithm for security purposes. Nonetheless MD5 has been used widely and if given a choice between storing a password in the clear or storing a salted and hashed password using MD5, I'd pick the latter.

Originally, I had a need for MD5 under MikroTik with the intent to check file integrity, to specifically determine whether a particular file had changed. When searching the forums other people were also looking for an MD5 script for other purposes. Someone on the forums was (and still may be) offering an MD5 script, for a small fee. I wanted a free solution, so I started to write my own MD5 script.

Ultimately, I ended up not using MD5 for my solution and I shelved the MD5 script. The MD5 script sat for a period of months at about 95% completed. It bothered me that I hadn't finished the MD5 script, so having a little time and revisiting the script I finished it and posted it here. If I had used the script as I had initially intended, the script would actually have one use case. Since at one time there was an expressed interest on the forums, http://forum.mikrotik.com/viewtopic.php ... 3&p=208825, I assume that there was or is an actual need for such a script and that there are actual cases of a similar script being in use.

Regards,
 
paris9
newbie
Posts: 32
Joined: Mon Feb 03, 2014 9:31 am

Re: Script MD5 Hash Generator

Sun Mar 30, 2014 12:47 am

I have been trying out your script and was wondering if you could help me with a problem. I have been unable to get a match with php's md5 for messages lengths over 55 chars. If you could provide any insight as to why this might be it would be greatly appreciated. I have included two debug logs, one with a message length of 55 chars and the second with 56 chars. The one with 56 chars fails to match with php's md5. Thanks much!


DEBUG OUTPUT FOR 55 CHARS


StrToMd5: Message: 0123456789012345678901234567890123456789012345678901234
StrToMd5: Message Length: 55
StrToMd5: Number of Words: 16
StrToMd5: parsed character $ch: '0' ASCII value $iCharVal: 48
StrToMd5: parsed character $ch: '1' ASCII value $iCharVal: 49
StrToMd5: parsed character $ch: '2' ASCII value $iCharVal: 50
StrToMd5: parsed character $ch: '3' ASCII value $iCharVal: 51
StrToMd5: parsed character $ch: '4' ASCII value $iCharVal: 52
StrToMd5: parsed character $ch: '5' ASCII value $iCharVal: 53
StrToMd5: parsed character $ch: '6' ASCII value $iCharVal: 54
StrToMd5: parsed character $ch: '7' ASCII value $iCharVal: 55
StrToMd5: parsed character $ch: '8' ASCII value $iCharVal: 56
StrToMd5: parsed character $ch: '9' ASCII value $iCharVal: 57
StrToMd5: parsed character $ch: '0' ASCII value $iCharVal: 48
StrToMd5: parsed character $ch: '1' ASCII value $iCharVal: 49
StrToMd5: parsed character $ch: '2' ASCII value $iCharVal: 50
StrToMd5: parsed character $ch: '3' ASCII value $iCharVal: 51
StrToMd5: parsed character $ch: '4' ASCII value $iCharVal: 52
StrToMd5: parsed character $ch: '5' ASCII value $iCharVal: 53
StrToMd5: parsed character $ch: '6' ASCII value $iCharVal: 54
StrToMd5: parsed character $ch: '7' ASCII value $iCharVal: 55
StrToMd5: parsed character $ch: '8' ASCII value $iCharVal: 56
StrToMd5: parsed character $ch: '9' ASCII value $iCharVal: 57
StrToMd5: parsed character $ch: '0' ASCII value $iCharVal: 48
StrToMd5: parsed character $ch: '1' ASCII value $iCharVal: 49
StrToMd5: parsed character $ch: '2' ASCII value $iCharVal: 50
StrToMd5: parsed character $ch: '3' ASCII value $iCharVal: 51
StrToMd5: parsed character $ch: '4' ASCII value $iCharVal: 52
StrToMd5: parsed character $ch: '5' ASCII value $iCharVal: 53
StrToMd5: parsed character $ch: '6' ASCII value $iCharVal: 54
StrToMd5: parsed character $ch: '7' ASCII value $iCharVal: 55
StrToMd5: parsed character $ch: '8' ASCII value $iCharVal: 56
StrToMd5: parsed character $ch: '9' ASCII value $iCharVal: 57
StrToMd5: parsed character $ch: '0' ASCII value $iCharVal: 48
StrToMd5: parsed character $ch: '1' ASCII value $iCharVal: 49
StrToMd5: parsed character $ch: '2' ASCII value $iCharVal: 50
StrToMd5: parsed character $ch: '3' ASCII value $iCharVal: 51
StrToMd5: parsed character $ch: '4' ASCII value $iCharVal: 52
StrToMd5: parsed character $ch: '5' ASCII value $iCharVal: 53
StrToMd5: parsed character $ch: '6' ASCII value $iCharVal: 54
StrToMd5: parsed character $ch: '7' ASCII value $iCharVal: 55
StrToMd5: parsed character $ch: '8' ASCII value $iCharVal: 56
StrToMd5: parsed character $ch: '9' ASCII value $iCharVal: 57
StrToMd5: parsed character $ch: '0' ASCII value $iCharVal: 48
StrToMd5: parsed character $ch: '1' ASCII value $iCharVal: 49
StrToMd5: parsed character $ch: '2' ASCII value $iCharVal: 50
StrToMd5: parsed character $ch: '3' ASCII value $iCharVal: 51
StrToMd5: parsed character $ch: '4' ASCII value $iCharVal: 52
StrToMd5: parsed character $ch: '5' ASCII value $iCharVal: 53
StrToMd5: parsed character $ch: '6' ASCII value $iCharVal: 54
StrToMd5: parsed character $ch: '7' ASCII value $iCharVal: 55
StrToMd5: parsed character $ch: '8' ASCII value $iCharVal: 56
StrToMd5: parsed character $ch: '9' ASCII value $iCharVal: 57
StrToMd5: parsed character $ch: '0' ASCII value $iCharVal: 48
StrToMd5: parsed character $ch: '1' ASCII value $iCharVal: 49
StrToMd5: parsed character $ch: '2' ASCII value $iCharVal: 50
StrToMd5: parsed character $ch: '3' ASCII value $iCharVal: 51
StrToMd5: parsed character $ch: '4' ASCII value $iCharVal: 52
StrToMd5: Round 1, Answer $tmp1: 1043889934
StrToMd5: Round 1, Answer $tmp1: 3976727801
StrToMd5: Round 1, Answer $tmp1: 1496991403
StrToMd5: Round 1, Answer $tmp1: 785365157
StrToMd5: Round 1, Answer $tmp1: 708128447
StrToMd5: Round 1, Answer $tmp1: 1090829548
StrToMd5: Round 1, Answer $tmp1: 507743179
StrToMd5: Round 1, Answer $tmp1: 350415511
StrToMd5: Round 1, Answer $tmp1: 758105254
StrToMd5: Round 1, Answer $tmp1: 2024392292
StrToMd5: Round 1, Answer $tmp1: 2205205030
StrToMd5: Round 1, Answer $tmp1: 246492053
StrToMd5: Round 1, Answer $tmp1: 589028787
StrToMd5: Round 1, Answer $tmp1: 2592589121
StrToMd5: Round 1, Answer $tmp1: 2290754940
StrToMd5: Round 1, Answer $tmp1: 3872072640
StrToMd5: Round 2, Answer $tmp1: 1177967738
StrToMd5: Round 2, Answer $tmp1: 3382687850
StrToMd5: Round 2, Answer $tmp1: 1442751009
StrToMd5: Round 2, Answer $tmp1: 564902236
StrToMd5: Round 2, Answer $tmp1: 3524707176
StrToMd5: Round 2, Answer $tmp1: 759797318
StrToMd5: Round 2, Answer $tmp1: 3289063093
StrToMd5: Round 2, Answer $tmp1: 3960348389
StrToMd5: Round 2, Answer $tmp1: 325783048
StrToMd5: Round 2, Answer $tmp1: 851916345
StrToMd5: Round 2, Answer $tmp1: 271384215
StrToMd5: Round 2, Answer $tmp1: 1669755681
StrToMd5: Round 2, Answer $tmp1: 1774915565
StrToMd5: Round 2, Answer $tmp1: 1276194165
StrToMd5: Round 2, Answer $tmp1: 2788600250
StrToMd5: Round 2, Answer $tmp1: 3488286956
StrToMd5: Round 3, Answer $tmp1: 4230705432
StrToMd5: Round 3, Answer $tmp1: 1835476493
StrToMd5: Round 3, Answer $tmp1: 225497022
StrToMd5: Round 3, Answer $tmp1: 3139819051
StrToMd5: Round 3, Answer $tmp1: 4031961270
StrToMd5: Round 3, Answer $tmp1: 532894330
StrToMd5: Round 3, Answer $tmp1: 3506494602
StrToMd5: Round 3, Answer $tmp1: 3656823063
StrToMd5: Round 3, Answer $tmp1: 3748878962
StrToMd5: Round 3, Answer $tmp1: 3197104922
StrToMd5: Round 3, Answer $tmp1: 391153224
StrToMd5: Round 3, Answer $tmp1: 1335277281
StrToMd5: Round 3, Answer $tmp1: 3694727214
StrToMd5: Round 3, Answer $tmp1: 3010396938
StrToMd5: Round 3, Answer $tmp1: 1551129277
StrToMd5: Round 3, Answer $tmp1: 1748018565
StrToMd5: Round 4, Answer $tmp1: 2121490450
StrToMd5: Round 4, Answer $tmp1: 3563463440
StrToMd5: Round 4, Answer $tmp1: 573078498
StrToMd5: Round 4, Answer $tmp1: 2680845324
StrToMd5: Round 4, Answer $tmp1: 1550383800
StrToMd5: Round 4, Answer $tmp1: 3474919971
StrToMd5: Round 4, Answer $tmp1: 3498841716
StrToMd5: Round 4, Answer $tmp1: 1564423957
StrToMd5: Round 4, Answer $tmp1: 195342272
StrToMd5: Round 4, Answer $tmp1: 1592538304
StrToMd5: Round 4, Answer $tmp1: 1340048581
StrToMd5: Round 4, Answer $tmp1: 3570997936
StrToMd5: Round 4, Answer $tmp1: 1644844909
StrToMd5: Round 4, Answer $tmp1: 2769434966
StrToMd5: Round 4, Answer $tmp1: 3263657448
StrToMd5: Round 4, Answer $tmp1: 116786597
6e7a4fc92eb1c3f6e652425bcc8d44b5
PHP MD5: 6e7a4fc92eb1c3f6e652425bcc8d44b5


DEBUG OUTPUT FOR 56 CHARS


StrToMd5: Message: 01234567890123456789012345678901234567890123456789012345
StrToMd5: Message Length: 56
StrToMd5: Number of Words: 32
StrToMd5: parsed character $ch: '0' ASCII value $iCharVal: 48
StrToMd5: parsed character $ch: '1' ASCII value $iCharVal: 49
StrToMd5: parsed character $ch: '2' ASCII value $iCharVal: 50
StrToMd5: parsed character $ch: '3' ASCII value $iCharVal: 51
StrToMd5: parsed character $ch: '4' ASCII value $iCharVal: 52
StrToMd5: parsed character $ch: '5' ASCII value $iCharVal: 53
StrToMd5: parsed character $ch: '6' ASCII value $iCharVal: 54
StrToMd5: parsed character $ch: '7' ASCII value $iCharVal: 55
StrToMd5: parsed character $ch: '8' ASCII value $iCharVal: 56
StrToMd5: parsed character $ch: '9' ASCII value $iCharVal: 57
StrToMd5: parsed character $ch: '0' ASCII value $iCharVal: 48
StrToMd5: parsed character $ch: '1' ASCII value $iCharVal: 49
StrToMd5: parsed character $ch: '2' ASCII value $iCharVal: 50
StrToMd5: parsed character $ch: '3' ASCII value $iCharVal: 51
StrToMd5: parsed character $ch: '4' ASCII value $iCharVal: 52
StrToMd5: parsed character $ch: '5' ASCII value $iCharVal: 53
StrToMd5: parsed character $ch: '6' ASCII value $iCharVal: 54
StrToMd5: parsed character $ch: '7' ASCII value $iCharVal: 55
StrToMd5: parsed character $ch: '8' ASCII value $iCharVal: 56
StrToMd5: parsed character $ch: '9' ASCII value $iCharVal: 57
StrToMd5: parsed character $ch: '0' ASCII value $iCharVal: 48
StrToMd5: parsed character $ch: '1' ASCII value $iCharVal: 49
StrToMd5: parsed character $ch: '2' ASCII value $iCharVal: 50
StrToMd5: parsed character $ch: '3' ASCII value $iCharVal: 51
StrToMd5: parsed character $ch: '4' ASCII value $iCharVal: 52
StrToMd5: parsed character $ch: '5' ASCII value $iCharVal: 53
StrToMd5: parsed character $ch: '6' ASCII value $iCharVal: 54
StrToMd5: parsed character $ch: '7' ASCII value $iCharVal: 55
StrToMd5: parsed character $ch: '8' ASCII value $iCharVal: 56
StrToMd5: parsed character $ch: '9' ASCII value $iCharVal: 57
StrToMd5: parsed character $ch: '0' ASCII value $iCharVal: 48
StrToMd5: parsed character $ch: '1' ASCII value $iCharVal: 49
StrToMd5: parsed character $ch: '2' ASCII value $iCharVal: 50
StrToMd5: parsed character $ch: '3' ASCII value $iCharVal: 51
StrToMd5: parsed character $ch: '4' ASCII value $iCharVal: 52
StrToMd5: parsed character $ch: '5' ASCII value $iCharVal: 53
StrToMd5: parsed character $ch: '6' ASCII value $iCharVal: 54
StrToMd5: parsed character $ch: '7' ASCII value $iCharVal: 55
StrToMd5: parsed character $ch: '8' ASCII value $iCharVal: 56
StrToMd5: parsed character $ch: '9' ASCII value $iCharVal: 57
StrToMd5: parsed character $ch: '0' ASCII value $iCharVal: 48
StrToMd5: parsed character $ch: '1' ASCII value $iCharVal: 49
StrToMd5: parsed character $ch: '2' ASCII value $iCharVal: 50
StrToMd5: parsed character $ch: '3' ASCII value $iCharVal: 51
StrToMd5: parsed character $ch: '4' ASCII value $iCharVal: 52
StrToMd5: parsed character $ch: '5' ASCII value $iCharVal: 53
StrToMd5: parsed character $ch: '6' ASCII value $iCharVal: 54
StrToMd5: parsed character $ch: '7' ASCII value $iCharVal: 55
StrToMd5: parsed character $ch: '8' ASCII value $iCharVal: 56
StrToMd5: parsed character $ch: '9' ASCII value $iCharVal: 57
StrToMd5: parsed character $ch: '0' ASCII value $iCharVal: 48
StrToMd5: parsed character $ch: '1' ASCII value $iCharVal: 49
StrToMd5: parsed character $ch: '2' ASCII value $iCharVal: 50
StrToMd5: parsed character $ch: '3' ASCII value $iCharVal: 51
StrToMd5: parsed character $ch: '4' ASCII value $iCharVal: 52
StrToMd5: parsed character $ch: '5' ASCII value $iCharVal: 53
StrToMd5: Round 1, Answer $tmp1: 1043889934
StrToMd5: Round 1, Answer $tmp1: 3976727801
StrToMd5: Round 1, Answer $tmp1: 1496991403
StrToMd5: Round 1, Answer $tmp1: 785365157
StrToMd5: Round 1, Answer $tmp1: 708128447
StrToMd5: Round 1, Answer $tmp1: 1090829548
StrToMd5: Round 1, Answer $tmp1: 507743179
StrToMd5: Round 1, Answer $tmp1: 350415511
StrToMd5: Round 1, Answer $tmp1: 758105254
StrToMd5: Round 1, Answer $tmp1: 2024392292
StrToMd5: Round 1, Answer $tmp1: 2205205030
StrToMd5: Round 1, Answer $tmp1: 246492053
StrToMd5: Round 1, Answer $tmp1: 589028787
StrToMd5: Round 1, Answer $tmp1: 2592587921
StrToMd5: Round 1, Answer $tmp1: 2115641548
StrToMd5: Round 1, Answer $tmp1: 3631676176
StrToMd5: Round 2, Answer $tmp1: 1784287161
StrToMd5: Round 2, Answer $tmp1: 1701006001
StrToMd5: Round 2, Answer $tmp1: 2770721335
StrToMd5: Round 2, Answer $tmp1: 2262270538
StrToMd5: Round 2, Answer $tmp1: 2268326889
StrToMd5: Round 2, Answer $tmp1: 568927790
StrToMd5: Round 2, Answer $tmp1: 1828849176
StrToMd5: Round 2, Answer $tmp1: 577691891
StrToMd5: Round 2, Answer $tmp1: 4184934364
StrToMd5: Round 2, Answer $tmp1: 328992381
StrToMd5: Round 2, Answer $tmp1: 657433351
StrToMd5: Round 2, Answer $tmp1: 3937119657
StrToMd5: Round 2, Answer $tmp1: 3510949256
StrToMd5: Round 2, Answer $tmp1: 1378320286
StrToMd5: Round 2, Answer $tmp1: 3914302571
StrToMd5: Round 2, Answer $tmp1: 31869769
StrToMd5: Round 3, Answer $tmp1: 4058338996
StrToMd5: Round 3, Answer $tmp1: 3288109044
StrToMd5: Round 3, Answer $tmp1: 1892110870
StrToMd5: Round 3, Answer $tmp1: 107521821
StrToMd5: Round 3, Answer $tmp1: 961001941
StrToMd5: Round 3, Answer $tmp1: 409290396
StrToMd5: Round 3, Answer $tmp1: 1197999769
StrToMd5: Round 3, Answer $tmp1: 2383894880
StrToMd5: Round 3, Answer $tmp1: 288337030
StrToMd5: Round 3, Answer $tmp1: 1573508346
StrToMd5: Round 3, Answer $tmp1: 3912624502
StrToMd5: Round 3, Answer $tmp1: 988659220
StrToMd5: Round 3, Answer $tmp1: 1607546607
StrToMd5: Round 3, Answer $tmp1: 1478383357
StrToMd5: Round 3, Answer $tmp1: 2626854136
StrToMd5: Round 3, Answer $tmp1: 3933778205
StrToMd5: Round 4, Answer $tmp1: 2422522843
StrToMd5: Round 4, Answer $tmp1: 3421437809
StrToMd5: Round 4, Answer $tmp1: 3398617929
StrToMd5: Round 4, Answer $tmp1: 517644729
StrToMd5: Round 4, Answer $tmp1: 3981120703
StrToMd5: Round 4, Answer $tmp1: 2208039566
StrToMd5: Round 4, Answer $tmp1: 558860515
StrToMd5: Round 4, Answer $tmp1: 3871410182
StrToMd5: Round 4, Answer $tmp1: 1540357410
StrToMd5: Round 4, Answer $tmp1: 2069010446
StrToMd5: Round 4, Answer $tmp1: 2102830634
StrToMd5: Round 4, Answer $tmp1: 4139035227
StrToMd5: Round 4, Answer $tmp1: 141808929
StrToMd5: Round 4, Answer $tmp1: 1431334097
StrToMd5: Round 4, Answer $tmp1: 46728212
StrToMd5: Round 4, Answer $tmp1: 3909142066
StrToMd5: Round 1, Answer $tmp1: 1043889934
StrToMd5: Round 1, Answer $tmp1: 3976727801
StrToMd5: Round 1, Answer $tmp1: 1496991403
StrToMd5: Round 1, Answer $tmp1: 785365157
StrToMd5: Round 1, Answer $tmp1: 708128447
StrToMd5: Round 1, Answer $tmp1: 1090829548
StrToMd5: Round 1, Answer $tmp1: 507743179
StrToMd5: Round 1, Answer $tmp1: 350415511
StrToMd5: Round 1, Answer $tmp1: 758105254
StrToMd5: Round 1, Answer $tmp1: 2024392292
StrToMd5: Round 1, Answer $tmp1: 2205205030
StrToMd5: Round 1, Answer $tmp1: 246492053
StrToMd5: Round 1, Answer $tmp1: 589028787
StrToMd5: Round 1, Answer $tmp1: 2592587921
StrToMd5: Round 1, Answer $tmp1: 2115641548
StrToMd5: Round 1, Answer $tmp1: 3631676176
StrToMd5: Round 2, Answer $tmp1: 1784287161
StrToMd5: Round 2, Answer $tmp1: 1701006001
StrToMd5: Round 2, Answer $tmp1: 2770721335
StrToMd5: Round 2, Answer $tmp1: 2262270538
StrToMd5: Round 2, Answer $tmp1: 2268326889
StrToMd5: Round 2, Answer $tmp1: 568927790
StrToMd5: Round 2, Answer $tmp1: 1828849176
StrToMd5: Round 2, Answer $tmp1: 577691891
StrToMd5: Round 2, Answer $tmp1: 4184934364
StrToMd5: Round 2, Answer $tmp1: 328992381
StrToMd5: Round 2, Answer $tmp1: 657433351
StrToMd5: Round 2, Answer $tmp1: 3937119657
StrToMd5: Round 2, Answer $tmp1: 3510949256
StrToMd5: Round 2, Answer $tmp1: 1378320286
StrToMd5: Round 2, Answer $tmp1: 3914302571
StrToMd5: Round 2, Answer $tmp1: 31869769
StrToMd5: Round 3, Answer $tmp1: 4058338996
StrToMd5: Round 3, Answer $tmp1: 3288109044
StrToMd5: Round 3, Answer $tmp1: 1892110870
StrToMd5: Round 3, Answer $tmp1: 107521821
StrToMd5: Round 3, Answer $tmp1: 961001941
StrToMd5: Round 3, Answer $tmp1: 409290396
StrToMd5: Round 3, Answer $tmp1: 1197999769
StrToMd5: Round 3, Answer $tmp1: 2383894880
StrToMd5: Round 3, Answer $tmp1: 288337030
StrToMd5: Round 3, Answer $tmp1: 1573508346
StrToMd5: Round 3, Answer $tmp1: 3912624502
StrToMd5: Round 3, Answer $tmp1: 988659220
StrToMd5: Round 3, Answer $tmp1: 1607546607
StrToMd5: Round 3, Answer $tmp1: 1478383357
StrToMd5: Round 3, Answer $tmp1: 2626854136
StrToMd5: Round 3, Answer $tmp1: 3933778205
StrToMd5: Round 4, Answer $tmp1: 2422522843
StrToMd5: Round 4, Answer $tmp1: 3421437809
StrToMd5: Round 4, Answer $tmp1: 3398617929
StrToMd5: Round 4, Answer $tmp1: 517644729
StrToMd5: Round 4, Answer $tmp1: 3981120703
StrToMd5: Round 4, Answer $tmp1: 2208039566
StrToMd5: Round 4, Answer $tmp1: 558860515
StrToMd5: Round 4, Answer $tmp1: 3871410182
StrToMd5: Round 4, Answer $tmp1: 1540357410
StrToMd5: Round 4, Answer $tmp1: 2069010446
StrToMd5: Round 4, Answer $tmp1: 2102830634
StrToMd5: Round 4, Answer $tmp1: 4139035227
StrToMd5: Round 4, Answer $tmp1: 141808929
StrToMd5: Round 4, Answer $tmp1: 1431334097
StrToMd5: Round 4, Answer $tmp1: 46728212
StrToMd5: Round 4, Answer $tmp1: 3909142066
22f8b86fbb71ced812e1839b47c18265
PHP MD5: 8af270b2847610e742b0791b53648c09
 
harsini
just joined
Posts: 2
Joined: Tue Oct 13, 2015 9:33 am

Re: Script MD5 Hash Generator

Sat Oct 24, 2015 11:53 am

Thanks for your nice hash function.Arrays defined like:
:local arrMd5State {}
should change to:
:local arrMd5State []
to work on ROS 6.25
 
fams
just joined
Posts: 2
Joined: Fri May 24, 2013 1:08 am

Re: Script MD5 Hash Generator

Thu Feb 11, 2016 5:24 pm

Thanks for the code, i patched the script to work as a function (v6.2+) debug as parameter and work with strings over 56bytes. Remember that MD5 is not collision resistent, i will write a SHA-1 version soon.
The first argument is the string, the second is a debug flag
# String message to MD5 Hash
# Creates a MD5 hash from a message string
# Version 1.00, 6/17/2012, Created by TealFrog
# Version 1.1 2/11/2016, Modified by FAMS
# Script tested and developed under MikroTik ROS 6.3 to 6.33
# 
#
# This software is identified as using and is based on the, "RSA Data Security, 
# Inc. MD5 Message-Digest Algorithm".  This program is a derived work from the RSA Data
# Security, Inc. MD5 Message-Digest Algorithm.
# See http://www.ietf.org/rfc/rfc1321.txt for further information.
#
# The author of this program makes no representations concerning either
# the merchantability of this software or the suitability of this
# software for any particular purpose or non-infringement.
# This program is provided "as is" without express or implied warranty of any kind.
# The author makes no representations or warranties of any kind as to the 
# completeness, accuracy, timeliness, availability, functionality and compliance
# with applicable laws. By using this software you accept the risk that the 
# information may be incomplete or inaccurate or may not meet your needs 
# and requirements. The author shall not be liable for any damages or 
# injury arising out of the use of this program. Use this program at your own risk. 
#
# MD5 has been shown to not be collision resistant, as such MD5 is not suitable 
# for certain applications involving security and/or cryptography, 
# see http://en.wikipedia.org/wiki/Md5 for additional information.
#
# $progName, Name of script, set appropriately
:global StrToMd5 do={

  :local progName "StrToMd5"
  :local strMessage $1
  # $strPrefix, Set to a prefix to add before MD5 hash, set "" for empty
  :local strPrefix ""

  # $strSuffix, Set to a suffix to add after MD5 hash, set "" for empty
  :local strSuffix ""
       # Set $Debug to 1 for additional output, set to zero to turn off debug
  :local Debug $2

  # $strHexValues, Used to create hexadecimal output
  :local strHexValues "0123456789abcdef"
  # To have uppercase hexadecimal A-F use the next line instead of the above
  # :local strHexValues "0123456789ABCDEF"

  # No futher modification required beyond this point unless customizing script
  # Start by defining constant values

  # ASCII Table $CharSet[0..127]
  :local arrCharSet ( "\00", "\01", "\02", "\03", "\04", "\05", "\06", "\07", \ 
                     "\08", "\09", "\0A", "\0B", "\0C", "\0D", "\0E", "\0F", \ 
                     "\10", "\11", "\12", "\13", "\14", "\15", "\16", "\17", \
                     "\18", "\19", "\1A", "\1B", "\1C", "\1D", "\1E", "\1F", \
                     "\20", "\21", "\22", "\23", "\24", "\25", "\26", "\27", \
                     "\28", "\29", "\2A", "\2B", "\2C", "\2D", "\2E", "\2F", \
                     "\30", "\31", "\32", "\33", "\34", "\35", "\36", "\37", \
                     "\38", "\39", "\3A", "\3B", "\3C", "\3D", "\3E", "\3F", \
                     "\40", "\41", "\42", "\43", "\44", "\45", "\46", "\47", \ 
                     "\48", "\49", "\4A", "\4B", "\4C", "\4D", "\4E", "\4F", \
                     "\50", "\51", "\52", "\53", "\54", "\55", "\56", "\57", \
                     "\58", "\59", "\5A", "\5B", "\5C", "\5D", "\5E", "\5F", \
                     "\60", "\61", "\62", "\63", "\64", "\65", "\66", "\67", \
                     "\68", "\69", "\6A", "\6B", "\6C", "\6D", "\6E", "\6F", \
                     "\70", "\71", "\72", "\73", "\74", "\75", "\76", "\77", \
                     "\78", "\79", "\7A", "\7B", "\7C", "\7D", "\7E", "\7F" ) 

  # k[i] = floor(abs(sin(i + 1))  4294967296) 
  # Or just use the following table $k[0..63]:
  :local k ( 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, \
            0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501, \
            0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, \
            0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821, \
            0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, \
            0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8, \
            0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, \
            0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A, \
            0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, \
            0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70, \
            0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, \
            0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665, \
            0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, \
            0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1, \
            0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, \
            0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391 )

  :local a 0x67452301 
  :local b 0xEFCDAB89
  :local c 0x98BADCFE
  :local d 0x10325476

  :local AA 0x67452301
  :local BB 0xEFCDAB89
  :local CC 0x98BADCFE
  :local DD 0x10325476

  :local s1 (  7, 12, 17, 22 )
  :local s2 (  5,  9, 14, 20 )
  :local s3 (  4, 11, 16, 23 )
  :local s4 (  6, 10, 15, 21 )

  :local i 0
  :local j 0
  :local x 0
  :local S 0
  :local T 0
  :local lcv 0
  :local tmp1 0

  :local arrMd5State []
  :local arrWordArray []
  :local ch ""
  :local iByteCount 0
  :local iCharVal 3
  :local iDec 0
  :local iHexDigit 8
  :local iMd5State 0
  :local lBytePosition 0
  :local lMessageLength 0
  :local lNumberOfWords 0        
  :local lShiftedVal 0
  :local lWordArray []
  :local lWordArrLen 0
  :local lWordCount 0
  :local sHex ""
  :local sMd5Hash ""
  :local sMd5Output ""
  :local strWordArray ""

  # Start of main program and message loop
  if ( $Debug > 0 ) do={
    :put "$progName: Running..."
    :put "$progName: Message: $strMessage"
  }
  :set ch ""
  :set lShiftedVal 0
  :set lWordCount 0
  :set iByteCount 0
  :set iCharVal 3
  :set lBytePosition 0
  :set lMessageLength [ :len $strMessage ]
  :set lNumberOfWords ( ( ( ( $lMessageLength + 8 ) / 64 ) + 1 ) * 16 )        
  :set strWordArray ""
  :set arrWordArray []

  # Convert to word array 
  :for i from=1 to=($lNumberOfWords) do={
    :set strWordArray ("0," . $strWordArray)
  }
  :set strWordArray  [ :pick $strWordArray 0 ( [ :len $strWordArray ] - 1 ) ]
  :set arrWordArray [ :toarray $strWordArray ]
  :if ( $Debug > 0 ) do={
    :put ("$progName: Message Length: " . $lMessageLength)
    :put ("$progName: Number of Words: " . $lNumberOfWords)
    :put ("$progName: strWordArray $strWordArray")
  }
  :while ($iByteCount < $lMessageLength) do={
    :set lWordCount ($iByteCount / 4)
    :set lBytePosition (($iByteCount % 4) * 8)
    :if (($lBytePosition < 0) or ($lBytePosition > 31)) do={
      :error ( "$progName: Error --  Calculating byte position " . \
          "# $lBytePosition, must be 0 thru 31." )
    }
    :set ch [ :pick $strMessage $iByteCount ]
    :if ( [ :len [ :find $arrCharSet $ch ] ] > 0 ) do={
      :set iCharVal ([ :tonum [ :find $arrCharSet $ch ] ])
    } else={
      :error "$progName: Error -- Input contains undefined ASCII value."
    }
    :if ( $Debug > 0 ) do={
      :put ( "$progName: parsed character \$ch: '$ch' " . \
        "ASCII value \$iCharVal: $iCharVal" )
    }
    :set lShiftedVal ((($iCharVal) << ($lBytePosition)) | \
                   (($iCharVal) >> (32-($lBytePosition))))
    :if ($iByteCount = 0) do={
      :set lShiftedVal (([ :tonum $lShiftedVal ] + 0) & 0xFFFFFFFF)
      :set arrWordArray (([ :tonum $lShiftedVal ]), \
                       [ :pick $arrWordArray 1 [ :len $arrWordArray] ])
    } else={
      :set lShiftedVal (([ :tonum [ :pick $arrWordArray $lWordCount] ] + 0) | \
                     ([ :tonum $lShiftedVal ] + 0))
      :set lShiftedVal (([ :tonum $lShiftedVal ] + 0) & 0xFFFFFFFF)
      :set arrWordArray  ([ :pick $arrWordArray 0 $lWordCount ], $lShiftedVal, \
         [ :pick $arrWordArray ([ :tonum $lWordCount ] + 1) [ :len $arrWordArray] ])   
    }
    :set iByteCount ( $iByteCount + 1 )
  }
  :set lWordCount ( $iByteCount / 4 )
  :set lBytePosition ( ( $iByteCount % 4 ) * 8 )
  :set lShiftedVal [ :pick $arrWordArray $lWordCount ]

  :set lShiftedVal ( ( [ :tonum [ :pick $arrWordArray $lWordCount ] ] + 0 ) | \
                   ( ( 0x80 << $lBytePosition ) | \
                 ( 0x80 >> ( 32 - $lBytePosition ) ) ) ) 

  :set arrWordArray  ( ( [ :pick $arrWordArray 0 $lWordCount ]  ),  \
                       [ :tonum $lShiftedVal ], \
                     ( [ :pick $arrWordArray ( [ :tonum $lWordCount ] + 1 ) \
                [ :len $arrWordArray ] ] ) ) 
                
  :set arrWordArray  [ :toarray ( ( [ :pick $arrWordArray 0 ($lNumberOfWords - 2) ] ), \
                              ( ( ( [ :tonum $lMessageLength ] + 0 ) << 3 ) | \
                       ( ( [ :tonum $lMessageLength ] + 0 ) >> 29 ) ), \
                       ( ( [ :tonum $lMessageLength ] + 0 )  >> 29 ) ) ] 
  :set lWordArray [ :toarray $arrWordArray ]
  :set lWordArrLen ( ( [ :len $lWordArray ] ) - 1 )
  :if ($Debug >0 ) do={
    :put "lWordArrLen $lWordArrLen"
  }
  ### Main Loop ###
  :set tmp1 0
  :set x 0
  :set T 0
  :set S 0
  :set i 0
  :set j 0
  :local iteration 0
  #:set a 0x67452301 
  #:set b 0xEFCDAB89
  #:set c 0x98BADCFE
  #:set d 0x10325476
  #Loop Principal
  :if ( $Debug >0 ) do={
    :put $lWordArray
  }
  :for lcv from=0 to=( $lWordArrLen ) step=16 do={
    :set AA [ :tonum $a ]
    :set BB [ :tonum $b ]
    :set CC [ :tonum $c ]
    :set DD [ :tonum $d ]
    :if ( $Debug > 0 ) do={
      :put $iteration
    }
    :local chuckoffset ($iteration * 16)
  ### Round 1 ### 
    :for i from=0 to=15 do={
      :set x ( [ :tonum [ :pick $lWordArray (( $i & 15 ) + $chuckoffset) ] ] + 0 )
      :set T ( [ :tonum [ :pick $k $i ] ] + 0 )
      :set S ( [ :tonum [ :pick $s1 ( $i & 3 ) ] ] + 0 )
  # Next line is an alternate mmethod, instead of the line after it     
  #         :set tmp1 ( ( (($b & $c) | (((($b + 1) * -1)) & $d)) + $a + $T + $x ) & 0xFFFFFFFF )
      :set tmp1 ( ( ( $d ^ ( $b & ( $c ^ $d ) ) ) + $a + $T + $x ) & 0xFFFFFFFF )
      :set tmp1 (((tmp1 << $S ) | (($tmp1 >> (32 - $S)))) & 0xFFFFFFFF)
      :set tmp1 ( ( $tmp1 + $b ) & 0xFFFFFFFF )
      :if ( $Debug > 0 ) do={         
         :put ("$progName: Round 1, Answer \$tmp1: $tmp1") 
      }            
  # Rotate a,b,c,d params positions, e.g. d, a, b, c ... c, d, a, b ... b, c, d, a 
  # and a gets new value from tmp1
      :set a ( ( [ :tonum $d ] + 0 ) & 0xFFFFFFFF )
      :set d ( ( [ :tonum $c ] + 0 ) & 0xFFFFFFFF )
      :set c ( ( [ :tonum $b ] + 0 ) & 0xFFFFFFFF )
      :set b ( ( [ :tonum $tmp1 ] + 0 ) & 0xFFFFFFFF )
    }

  ### Round 2 ###
    :set j 1
    :for i from=0 to=15 do={
      :set x ( [ :tonum [ :pick $lWordArray (( ( [ :tonum $j ] + 0 ) & 15 ) + $chuckoffset ) ] ] + 0 )
      :set T ( [ :tonum [ :pick $k ( $i + 16 ) ] ] + 0 )
      :set S ( [ :tonum [ :pick $s2 ( $i & 3 ) ] ] + 0 )
      :set tmp1 ( ( ( $c ^ ( $d & ( $b ^ $c ) ) ) + $a + $T + $x ) & 0xFFFFFFFF )
      :set tmp1 (((tmp1 << $S ) | (($tmp1 >> (32 - $S)))) & 0xFFFFFFFF)
      :set tmp1 ( ( $tmp1 + $b ) & 0xFFFFFFFF )
      :if ( $Debug > 0 ) do={         
         :put ("$progName: Round 2, Answer \$tmp1: $tmp1") 
      }
  # Rotate a,b,c,d param positions, e.g. d, a, b, c ... c, d, a, b ... b, c, d, a
      :set a ( ( [ :tonum $d ] + 0 ) & 0xFFFFFFFF )
      :set d ( ( [ :tonum $c ] + 0 ) & 0xFFFFFFFF )
      :set c ( ( [ :tonum $b ] + 0 ) & 0xFFFFFFFF )
      :set b ( ( [ :tonum $tmp1 ] + 0 ) & 0xFFFFFFFF )
      :set j ( $j + 5 )
    }
   
  ### Round 3 ###
    :set j 5
    :for i from=0 to=15 do={
      :set x ( [ :tonum [ :pick $lWordArray ( ( ( [ :tonum $j ] + 0 ) & 15 ) + $chuckoffset) ] ] + 0 )
      :set T ( [ :tonum [ :pick $k ( $i + 32 ) ] ] + 0 )
      :set S ( [ :tonum [ :pick $s3 ( $i & 3 ) ] ] + 0 )
      :set tmp1 ( ( ( $b ^ $c ^ $d ) + $a + $T + $x ) & 0xFFFFFFFF )
      :set tmp1 (((tmp1 << $S ) | (($tmp1 >> (32 - $S)))) & 0xFFFFFFFF)
      :set tmp1 ( ( $tmp1 + $b ) & 0xFFFFFFFF )
      :if ( $Debug > 0 ) do={         
         :put ("$progName: Round 3, Answer \$tmp1: $tmp1") 
      }            
  # Rotate a,b,c,d param positions, e.g. d, a, b, c ... c, d, a, b ... b, c, d, a
      :set a ( ( [ :tonum $d ] + 0) & 0xFFFFFFFF )
      :set d ( ( [ :tonum $c ] + 0) & 0xFFFFFFFF )
      :set c ( ( [ :tonum $b ] + 0) & 0xFFFFFFFF )
      :set b ( ( [ :tonum $tmp1 ] + 0) & 0xFFFFFFFF )
      :set j ( $j + 3 )
    }
   
  ### Round 4 ###
    :set j 0
    :for i from=0 to=15 do={
      :set x ( [ :tonum [ :pick $lWordArray  ( ( ( [ :tonum $j ] + 0 ) & 15 ) + $chuckoffset ) ] ] + 0 )
      :set T ( [ :tonum [ :pick $k ( $i + 48 ) ] ] + 0 )
      :set S ( [ :tonum [ :pick $s4 ( $i & 3 ) ] ] + 0 )
  # Next line is alternate method to the line following     
  #         :set tmp1 ( $c ^ ( $b | ( ( $d & 0xFFFFFFFF ) ^ 0xFFFFFFFF ) ) )
      :set tmp1 ( ( $c ^ ( $b | ( -1 * ( $d + 1 ) ) ) ) & 0xFFFFFFFF )
      :set tmp1 ( ( $tmp1 + $a + $T + $x ) & 0xFFFFFFFF )
      :set tmp1 ( ((tmp1 << $S ) | (($tmp1 >> (32 - $S)))) & 0xFFFFFFFF )
      :set tmp1 ( ( $tmp1 + $b ) & 0xFFFFFFFF )
      :if ( $Debug > 0 ) do={         
         :put ("$progName: Round 4, Answer \$tmp1: $tmp1") 
      }            
  # Rotate a,b,c,d param positions, e.g. d, a, b, c ... c, d, a, b ... b, c, d, a
      :set a ( ( [ :tonum $d ] + 0) & 0xFFFFFFFF )
      :set d ( ( [ :tonum $c ] + 0) & 0xFFFFFFFF )
      :set c ( ( [ :tonum $b ] + 0) & 0xFFFFFFFF )
      :set b ( ( [ :tonum $tmp1 ] + 0) & 0xFFFFFFFF )
      :set j ( $j + 7 )
    }
    :if ( $Debug > 0 ) do={      
      :put "Iteration $iteration = $a | $b | $c | $d"
    }
    :set a ( ( $a + $AA ) & 0xFFFFFFFF )    
    :set b ( ( $b + $BB ) & 0xFFFFFFFF )    
    :set c ( ( $c + $CC ) & 0xFFFFFFFF )    
    :set d ( ( $d + $DD ) & 0xFFFFFFFF ) 
    :set iteration ( $iteration +1 ) 
  }

  :set arrMd5State [ :toarray "$a, $b, $c, $d" ]
  :set sMd5Hash ""
  :set sMd5Output ""
  :set iDec 0
  :set iMd5State 0
  :set sHex ""
  :for i from=0 to=3 do={
    :set iMd5State [ :pick $arrMd5State $i ]      
    :for j from=0 to=3 do={
      :set iMd5State ( [ :tonum $iMd5State ] & 0xFFFFFFFF )
      :if ( $j < 1 ) do={
         :set iDec ( [ :tonum $iMd5State ] & 255 )
      } else={
        :set iDec ( ( $iMd5State & 0x7FFFFFFE ) / ( 2 << ( ( $j * 8 ) - 1 ) ) )
        :if ( ( $iMd5State & 0x80000000 ) > 0 ) do={
          :set iDec ( $iDec | ( 0x40000000 /  ( 2 << ( ( $j * 8 ) - 2 ) ) ) )
        }
        :set iDec ( $iDec & 0xFF ) 
      } 
      :set sHex ""
      :for k from=0 to=( 4 * ( $iHexDigit - 1 ) ) step=4 do={
        :set sHex ( [ :pick [ :tostr $strHexValues ] \
        ( ( $iDec >> $k ) & 0xF ) \ 
        ( ( ( $iDec >> $k ) & 0xF ) + 1 ) ] . $sHex ) 
      }
      :set sHex [ :tostr $sHex ]
      :set sHex [ :pick $sHex ( [ :len $sHex ] - 2 ) [ :len $sHex ] ]
      :set sMd5Output ( $sMd5Output . $sHex )     
    }
  }
  # Modify next line to customize MD5 output string     
  :put [( [ :tostr $strPrefix ] . [ :tostr $sMd5Output ] . [ :tostr $strSuffix ] )]
  if ( $Debug > 0 ) do={
    :put "$progName: Done."
  }
}
 
sejtam
Frequent Visitor
Frequent Visitor
Posts: 67
Joined: Sun Dec 14, 2014 4:23 pm

Re: Script MD5 Hash Generator

Tue Jan 09, 2018 3:11 pm

I am not so fluent in The ROS language. Could someone show an example
how to call this as a function?

I looked at

https://wiki.mikrotik.com/wiki/Use_Func ... CMD_Script

But that method is somewhat different?

thanks
 
p0we7
just joined
Posts: 1
Joined: Thu Feb 13, 2020 6:39 pm

Re: Script MD5 Hash Generator

Thu Feb 13, 2020 6:45 pm

Hello, I saw that you said to write a SHA-1 version, has it been released?

Thanks for the code, i patched the script to work as a function (v6.2+) debug as parameter and work with strings over 56bytes. Remember that MD5 is not collision resistent, i will write a SHA-1 version soon.
The first argument is the string, the second is a debug flag
# String message to MD5 Hash
# Creates a MD5 hash from a message string
# Version 1.00, 6/17/2012, Created by TealFrog
# Version 1.1 2/11/2016, Modified by FAMS
# Script tested and developed under MikroTik ROS 6.3 to 6.33
# 
#
# This software is identified as using and is based on the, "RSA Data Security, 
# Inc. MD5 Message-Digest Algorithm".  This program is a derived work from the RSA Data
# Security, Inc. MD5 Message-Digest Algorithm.
# See http://www.ietf.org/rfc/rfc1321.txt for further information.
#
# The author of this program makes no representations concerning either
# the merchantability of this software or the suitability of this
# software for any particular purpose or non-infringement.
# This program is provided "as is" without express or implied warranty of any kind.
# The author makes no representations or warranties of any kind as to the 
# completeness, accuracy, timeliness, availability, functionality and compliance
# with applicable laws. By using this software you accept the risk that the 
# information may be incomplete or inaccurate or may not meet your needs 
# and requirements. The author shall not be liable for any damages or 
# injury arising out of the use of this program. Use this program at your own risk. 
#
# MD5 has been shown to not be collision resistant, as such MD5 is not suitable 
# for certain applications involving security and/or cryptography, 
# see http://en.wikipedia.org/wiki/Md5 for additional information.
#
# $progName, Name of script, set appropriately
:global StrToMd5 do={

  :local progName "StrToMd5"
  :local strMessage $1
  # $strPrefix, Set to a prefix to add before MD5 hash, set "" for empty
  :local strPrefix ""

  # $strSuffix, Set to a suffix to add after MD5 hash, set "" for empty
  :local strSuffix ""
       # Set $Debug to 1 for additional output, set to zero to turn off debug
  :local Debug $2

  # $strHexValues, Used to create hexadecimal output
  :local strHexValues "0123456789abcdef"
  # To have uppercase hexadecimal A-F use the next line instead of the above
  # :local strHexValues "0123456789ABCDEF"

  # No futher modification required beyond this point unless customizing script
  # Start by defining constant values

  # ASCII Table $CharSet[0..127]
  :local arrCharSet ( "\00", "\01", "\02", "\03", "\04", "\05", "\06", "\07", \ 
                     "\08", "\09", "\0A", "\0B", "\0C", "\0D", "\0E", "\0F", \ 
                     "\10", "\11", "\12", "\13", "\14", "\15", "\16", "\17", \
                     "\18", "\19", "\1A", "\1B", "\1C", "\1D", "\1E", "\1F", \
                     "\20", "\21", "\22", "\23", "\24", "\25", "\26", "\27", \
                     "\28", "\29", "\2A", "\2B", "\2C", "\2D", "\2E", "\2F", \
                     "\30", "\31", "\32", "\33", "\34", "\35", "\36", "\37", \
                     "\38", "\39", "\3A", "\3B", "\3C", "\3D", "\3E", "\3F", \
                     "\40", "\41", "\42", "\43", "\44", "\45", "\46", "\47", \ 
                     "\48", "\49", "\4A", "\4B", "\4C", "\4D", "\4E", "\4F", \
                     "\50", "\51", "\52", "\53", "\54", "\55", "\56", "\57", \
                     "\58", "\59", "\5A", "\5B", "\5C", "\5D", "\5E", "\5F", \
                     "\60", "\61", "\62", "\63", "\64", "\65", "\66", "\67", \
                     "\68", "\69", "\6A", "\6B", "\6C", "\6D", "\6E", "\6F", \
                     "\70", "\71", "\72", "\73", "\74", "\75", "\76", "\77", \
                     "\78", "\79", "\7A", "\7B", "\7C", "\7D", "\7E", "\7F" ) 

  # k[i] = floor(abs(sin(i + 1))  4294967296) 
  # Or just use the following table $k[0..63]:
  :local k ( 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, \
            0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501, \
            0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, \
            0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821, \
            0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, \
            0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8, \
            0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, \
            0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A, \
            0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, \
            0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70, \
            0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, \
            0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665, \
            0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, \
            0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1, \
            0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, \
            0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391 )

  :local a 0x67452301 
  :local b 0xEFCDAB89
  :local c 0x98BADCFE
  :local d 0x10325476

  :local AA 0x67452301
  :local BB 0xEFCDAB89
  :local CC 0x98BADCFE
  :local DD 0x10325476

  :local s1 (  7, 12, 17, 22 )
  :local s2 (  5,  9, 14, 20 )
  :local s3 (  4, 11, 16, 23 )
  :local s4 (  6, 10, 15, 21 )

  :local i 0
  :local j 0
  :local x 0
  :local S 0
  :local T 0
  :local lcv 0
  :local tmp1 0

  :local arrMd5State []
  :local arrWordArray []
  :local ch ""
  :local iByteCount 0
  :local iCharVal 3
  :local iDec 0
  :local iHexDigit 8
  :local iMd5State 0
  :local lBytePosition 0
  :local lMessageLength 0
  :local lNumberOfWords 0        
  :local lShiftedVal 0
  :local lWordArray []
  :local lWordArrLen 0
  :local lWordCount 0
  :local sHex ""
  :local sMd5Hash ""
  :local sMd5Output ""
  :local strWordArray ""

  # Start of main program and message loop
  if ( $Debug > 0 ) do={
    :put "$progName: Running..."
    :put "$progName: Message: $strMessage"
  }
  :set ch ""
  :set lShiftedVal 0
  :set lWordCount 0
  :set iByteCount 0
  :set iCharVal 3
  :set lBytePosition 0
  :set lMessageLength [ :len $strMessage ]
  :set lNumberOfWords ( ( ( ( $lMessageLength + 8 ) / 64 ) + 1 ) * 16 )        
  :set strWordArray ""
  :set arrWordArray []

  # Convert to word array 
  :for i from=1 to=($lNumberOfWords) do={
    :set strWordArray ("0," . $strWordArray)
  }
  :set strWordArray  [ :pick $strWordArray 0 ( [ :len $strWordArray ] - 1 ) ]
  :set arrWordArray [ :toarray $strWordArray ]
  :if ( $Debug > 0 ) do={
    :put ("$progName: Message Length: " . $lMessageLength)
    :put ("$progName: Number of Words: " . $lNumberOfWords)
    :put ("$progName: strWordArray $strWordArray")
  }
  :while ($iByteCount < $lMessageLength) do={
    :set lWordCount ($iByteCount / 4)
    :set lBytePosition (($iByteCount % 4) * 8)
    :if (($lBytePosition < 0) or ($lBytePosition > 31)) do={
      :error ( "$progName: Error --  Calculating byte position " . \
          "# $lBytePosition, must be 0 thru 31." )
    }
    :set ch [ :pick $strMessage $iByteCount ]
    :if ( [ :len [ :find $arrCharSet $ch ] ] > 0 ) do={
      :set iCharVal ([ :tonum [ :find $arrCharSet $ch ] ])
    } else={
      :error "$progName: Error -- Input contains undefined ASCII value."
    }
    :if ( $Debug > 0 ) do={
      :put ( "$progName: parsed character \$ch: '$ch' " . \
        "ASCII value \$iCharVal: $iCharVal" )
    }
    :set lShiftedVal ((($iCharVal) << ($lBytePosition)) | \
                   (($iCharVal) >> (32-($lBytePosition))))
    :if ($iByteCount = 0) do={
      :set lShiftedVal (([ :tonum $lShiftedVal ] + 0) & 0xFFFFFFFF)
      :set arrWordArray (([ :tonum $lShiftedVal ]), \
                       [ :pick $arrWordArray 1 [ :len $arrWordArray] ])
    } else={
      :set lShiftedVal (([ :tonum [ :pick $arrWordArray $lWordCount] ] + 0) | \
                     ([ :tonum $lShiftedVal ] + 0))
      :set lShiftedVal (([ :tonum $lShiftedVal ] + 0) & 0xFFFFFFFF)
      :set arrWordArray  ([ :pick $arrWordArray 0 $lWordCount ], $lShiftedVal, \
         [ :pick $arrWordArray ([ :tonum $lWordCount ] + 1) [ :len $arrWordArray] ])   
    }
    :set iByteCount ( $iByteCount + 1 )
  }
  :set lWordCount ( $iByteCount / 4 )
  :set lBytePosition ( ( $iByteCount % 4 ) * 8 )
  :set lShiftedVal [ :pick $arrWordArray $lWordCount ]

  :set lShiftedVal ( ( [ :tonum [ :pick $arrWordArray $lWordCount ] ] + 0 ) | \
                   ( ( 0x80 << $lBytePosition ) | \
                 ( 0x80 >> ( 32 - $lBytePosition ) ) ) ) 

  :set arrWordArray  ( ( [ :pick $arrWordArray 0 $lWordCount ]  ),  \
                       [ :tonum $lShiftedVal ], \
                     ( [ :pick $arrWordArray ( [ :tonum $lWordCount ] + 1 ) \
                [ :len $arrWordArray ] ] ) ) 
                
  :set arrWordArray  [ :toarray ( ( [ :pick $arrWordArray 0 ($lNumberOfWords - 2) ] ), \
                              ( ( ( [ :tonum $lMessageLength ] + 0 ) << 3 ) | \
                       ( ( [ :tonum $lMessageLength ] + 0 ) >> 29 ) ), \
                       ( ( [ :tonum $lMessageLength ] + 0 )  >> 29 ) ) ] 
  :set lWordArray [ :toarray $arrWordArray ]
  :set lWordArrLen ( ( [ :len $lWordArray ] ) - 1 )
  :if ($Debug >0 ) do={
    :put "lWordArrLen $lWordArrLen"
  }
  ### Main Loop ###
  :set tmp1 0
  :set x 0
  :set T 0
  :set S 0
  :set i 0
  :set j 0
  :local iteration 0
  #:set a 0x67452301 
  #:set b 0xEFCDAB89
  #:set c 0x98BADCFE
  #:set d 0x10325476
  #Loop Principal
  :if ( $Debug >0 ) do={
    :put $lWordArray
  }
  :for lcv from=0 to=( $lWordArrLen ) step=16 do={
    :set AA [ :tonum $a ]
    :set BB [ :tonum $b ]
    :set CC [ :tonum $c ]
    :set DD [ :tonum $d ]
    :if ( $Debug > 0 ) do={
      :put $iteration
    }
    :local chuckoffset ($iteration * 16)
  ### Round 1 ### 
    :for i from=0 to=15 do={
      :set x ( [ :tonum [ :pick $lWordArray (( $i & 15 ) + $chuckoffset) ] ] + 0 )
      :set T ( [ :tonum [ :pick $k $i ] ] + 0 )
      :set S ( [ :tonum [ :pick $s1 ( $i & 3 ) ] ] + 0 )
  # Next line is an alternate mmethod, instead of the line after it     
  #         :set tmp1 ( ( (($b & $c) | (((($b + 1) * -1)) & $d)) + $a + $T + $x ) & 0xFFFFFFFF )
      :set tmp1 ( ( ( $d ^ ( $b & ( $c ^ $d ) ) ) + $a + $T + $x ) & 0xFFFFFFFF )
      :set tmp1 (((tmp1 << $S ) | (($tmp1 >> (32 - $S)))) & 0xFFFFFFFF)
      :set tmp1 ( ( $tmp1 + $b ) & 0xFFFFFFFF )
      :if ( $Debug > 0 ) do={         
         :put ("$progName: Round 1, Answer \$tmp1: $tmp1") 
      }            
  # Rotate a,b,c,d params positions, e.g. d, a, b, c ... c, d, a, b ... b, c, d, a 
  # and a gets new value from tmp1
      :set a ( ( [ :tonum $d ] + 0 ) & 0xFFFFFFFF )
      :set d ( ( [ :tonum $c ] + 0 ) & 0xFFFFFFFF )
      :set c ( ( [ :tonum $b ] + 0 ) & 0xFFFFFFFF )
      :set b ( ( [ :tonum $tmp1 ] + 0 ) & 0xFFFFFFFF )
    }

  ### Round 2 ###
    :set j 1
    :for i from=0 to=15 do={
      :set x ( [ :tonum [ :pick $lWordArray (( ( [ :tonum $j ] + 0 ) & 15 ) + $chuckoffset ) ] ] + 0 )
      :set T ( [ :tonum [ :pick $k ( $i + 16 ) ] ] + 0 )
      :set S ( [ :tonum [ :pick $s2 ( $i & 3 ) ] ] + 0 )
      :set tmp1 ( ( ( $c ^ ( $d & ( $b ^ $c ) ) ) + $a + $T + $x ) & 0xFFFFFFFF )
      :set tmp1 (((tmp1 << $S ) | (($tmp1 >> (32 - $S)))) & 0xFFFFFFFF)
      :set tmp1 ( ( $tmp1 + $b ) & 0xFFFFFFFF )
      :if ( $Debug > 0 ) do={         
         :put ("$progName: Round 2, Answer \$tmp1: $tmp1") 
      }
  # Rotate a,b,c,d param positions, e.g. d, a, b, c ... c, d, a, b ... b, c, d, a
      :set a ( ( [ :tonum $d ] + 0 ) & 0xFFFFFFFF )
      :set d ( ( [ :tonum $c ] + 0 ) & 0xFFFFFFFF )
      :set c ( ( [ :tonum $b ] + 0 ) & 0xFFFFFFFF )
      :set b ( ( [ :tonum $tmp1 ] + 0 ) & 0xFFFFFFFF )
      :set j ( $j + 5 )
    }
   
  ### Round 3 ###
    :set j 5
    :for i from=0 to=15 do={
      :set x ( [ :tonum [ :pick $lWordArray ( ( ( [ :tonum $j ] + 0 ) & 15 ) + $chuckoffset) ] ] + 0 )
      :set T ( [ :tonum [ :pick $k ( $i + 32 ) ] ] + 0 )
      :set S ( [ :tonum [ :pick $s3 ( $i & 3 ) ] ] + 0 )
      :set tmp1 ( ( ( $b ^ $c ^ $d ) + $a + $T + $x ) & 0xFFFFFFFF )
      :set tmp1 (((tmp1 << $S ) | (($tmp1 >> (32 - $S)))) & 0xFFFFFFFF)
      :set tmp1 ( ( $tmp1 + $b ) & 0xFFFFFFFF )
      :if ( $Debug > 0 ) do={         
         :put ("$progName: Round 3, Answer \$tmp1: $tmp1") 
      }            
  # Rotate a,b,c,d param positions, e.g. d, a, b, c ... c, d, a, b ... b, c, d, a
      :set a ( ( [ :tonum $d ] + 0) & 0xFFFFFFFF )
      :set d ( ( [ :tonum $c ] + 0) & 0xFFFFFFFF )
      :set c ( ( [ :tonum $b ] + 0) & 0xFFFFFFFF )
      :set b ( ( [ :tonum $tmp1 ] + 0) & 0xFFFFFFFF )
      :set j ( $j + 3 )
    }
   
  ### Round 4 ###
    :set j 0
    :for i from=0 to=15 do={
      :set x ( [ :tonum [ :pick $lWordArray  ( ( ( [ :tonum $j ] + 0 ) & 15 ) + $chuckoffset ) ] ] + 0 )
      :set T ( [ :tonum [ :pick $k ( $i + 48 ) ] ] + 0 )
      :set S ( [ :tonum [ :pick $s4 ( $i & 3 ) ] ] + 0 )
  # Next line is alternate method to the line following     
  #         :set tmp1 ( $c ^ ( $b | ( ( $d & 0xFFFFFFFF ) ^ 0xFFFFFFFF ) ) )
      :set tmp1 ( ( $c ^ ( $b | ( -1 * ( $d + 1 ) ) ) ) & 0xFFFFFFFF )
      :set tmp1 ( ( $tmp1 + $a + $T + $x ) & 0xFFFFFFFF )
      :set tmp1 ( ((tmp1 << $S ) | (($tmp1 >> (32 - $S)))) & 0xFFFFFFFF )
      :set tmp1 ( ( $tmp1 + $b ) & 0xFFFFFFFF )
      :if ( $Debug > 0 ) do={         
         :put ("$progName: Round 4, Answer \$tmp1: $tmp1") 
      }            
  # Rotate a,b,c,d param positions, e.g. d, a, b, c ... c, d, a, b ... b, c, d, a
      :set a ( ( [ :tonum $d ] + 0) & 0xFFFFFFFF )
      :set d ( ( [ :tonum $c ] + 0) & 0xFFFFFFFF )
      :set c ( ( [ :tonum $b ] + 0) & 0xFFFFFFFF )
      :set b ( ( [ :tonum $tmp1 ] + 0) & 0xFFFFFFFF )
      :set j ( $j + 7 )
    }
    :if ( $Debug > 0 ) do={      
      :put "Iteration $iteration = $a | $b | $c | $d"
    }
    :set a ( ( $a + $AA ) & 0xFFFFFFFF )    
    :set b ( ( $b + $BB ) & 0xFFFFFFFF )    
    :set c ( ( $c + $CC ) & 0xFFFFFFFF )    
    :set d ( ( $d + $DD ) & 0xFFFFFFFF ) 
    :set iteration ( $iteration +1 ) 
  }

  :set arrMd5State [ :toarray "$a, $b, $c, $d" ]
  :set sMd5Hash ""
  :set sMd5Output ""
  :set iDec 0
  :set iMd5State 0
  :set sHex ""
  :for i from=0 to=3 do={
    :set iMd5State [ :pick $arrMd5State $i ]      
    :for j from=0 to=3 do={
      :set iMd5State ( [ :tonum $iMd5State ] & 0xFFFFFFFF )
      :if ( $j < 1 ) do={
         :set iDec ( [ :tonum $iMd5State ] & 255 )
      } else={
        :set iDec ( ( $iMd5State & 0x7FFFFFFE ) / ( 2 << ( ( $j * 8 ) - 1 ) ) )
        :if ( ( $iMd5State & 0x80000000 ) > 0 ) do={
          :set iDec ( $iDec | ( 0x40000000 /  ( 2 << ( ( $j * 8 ) - 2 ) ) ) )
        }
        :set iDec ( $iDec & 0xFF ) 
      } 
      :set sHex ""
      :for k from=0 to=( 4 * ( $iHexDigit - 1 ) ) step=4 do={
        :set sHex ( [ :pick [ :tostr $strHexValues ] \
        ( ( $iDec >> $k ) & 0xF ) \ 
        ( ( ( $iDec >> $k ) & 0xF ) + 1 ) ] . $sHex ) 
      }
      :set sHex [ :tostr $sHex ]
      :set sHex [ :pick $sHex ( [ :len $sHex ] - 2 ) [ :len $sHex ] ]
      :set sMd5Output ( $sMd5Output . $sHex )     
    }
  }
  # Modify next line to customize MD5 output string     
  :put [( [ :tostr $strPrefix ] . [ :tostr $sMd5Output ] . [ :tostr $strSuffix ] )]
  if ( $Debug > 0 ) do={
    :put "$progName: Done."
  }
}
Last edited by p0we7 on Thu Feb 13, 2020 6:46 pm, edited 1 time in total.
 
salmangalileo
just joined
Posts: 2
Joined: Mon Feb 08, 2021 11:29 am

Re: Script MD5 Hash Generator

Fri Feb 12, 2021 11:09 am

Is this script only work with ascii character? i try to used it to compute chap-id and chap-challange and it give error message. is this hash different from md5.js?
 
richardsu
just joined
Posts: 11
Joined: Mon Aug 01, 2016 7:59 pm

Re: Script MD5 Hash Generator

Fri Mar 26, 2021 5:35 am

how to run in scheduler?
 
User avatar
merlinthemagic7
newbie
Posts: 47
Joined: Fri Sep 16, 2016 8:49 pm

Re: Script MD5 Hash Generator

Sat Oct 02, 2021 2:39 pm

Hi @TealFrog,

I included your MD5 function (with attribution) in my ROS lib, There is no license on your work so let me know if you want it removed.

https://github.com/merlinthemagic/MTM-R ... -Scripting
/import flash/MTM/Facts.rsc;
:global MtmFacts;

:local md5Tool [($MtmFacts->"execute") nsStr="getTools()->getHashing()->getMD5()"];
:put ([($md5Tool->"hash") "my string data"]); ## outputs: "8240143bd807e5a52b1f9d7dd5e21ef3"
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Script MD5 Hash Generator

Sat Oct 02, 2021 3:49 pm

I must admit than you are really polite, because not often I see someone that ask permission, when the others neither thanks for the use...

Thanks.
 
brachux
just joined
Posts: 3
Joined: Thu Sep 03, 2015 12:35 pm
Contact:

Re: Script MD5 Hash Generator

Thu Jan 12, 2023 7:36 pm

Hi, nice work. Do you see it possible to use this MD5 script to implement in Mikrotik scripting for using it with fetch and Digest Authentication?
At the moment only plain Basic Authentication is supported.
 
alexbayker
just joined
Posts: 4
Joined: Mon Dec 25, 2023 5:15 pm

Re: Script MD5 Hash Generator

Mon Dec 25, 2023 5:16 pm

Digest authentication was implemented in firmware 7.13
fetch - added "http-auth-scheme" parameter, allows to select HTTP basic or digest authentication;
Last edited by alexbayker on Mon Dec 25, 2023 5:18 pm, edited 2 times in total.
 
alexbayker
just joined
Posts: 4
Joined: Mon Dec 25, 2023 5:15 pm

Re: Script MD5 Hash Generator

Mon Dec 25, 2023 5:20 pm

Who can help with getting the SHA1-hash from a string variable in scripts?
 
optio
Long time Member
Long time Member
Posts: 655
Joined: Mon Dec 26, 2022 2:57 pm

Re: Script MD5 Hash Generator

Mon Dec 25, 2023 6:21 pm

If you cannot find already created function for this, you can use some online API (if router can access it) for such operations, like hashify.net (not recommended to use it for passwords).
Example (ROS 7.13+ because of :deserialize usage):
:local str "Hello World!"
:local method "SHA1"
:local hash ([:deserialize ([/tool/fetch url="https://api.hashify.net/hash/$method/hex?value=$str" output=user as-value]->"data") from=json]->"Digest")
:put $hash
 
User avatar
diamuxin
Member
Member
Posts: 319
Joined: Thu Sep 09, 2021 5:46 pm
Location: Alhambra's City

Re: Script MD5 Hash Generator

Mon Dec 25, 2023 6:31 pm

Very interesting.. Thanks.
 
optio
Long time Member
Long time Member
Posts: 655
Joined: Mon Dec 26, 2022 2:57 pm

Re: Script MD5 Hash Generator

Mon Dec 25, 2023 7:36 pm

Np, API can be also provided by ROS container since is open source - https://github.com/dwin/hashify, then you don't need to worry which data is sent to remote site if you know how to review code to be safe, build and create container image with it.
There is also great online tool called CyberChef with various useful functions which also can be provided over API with CyberChef-server in container, here is Dockerfile for building it.
 
alexbayker
just joined
Posts: 4
Joined: Mon Dec 25, 2023 5:15 pm

Re: Script MD5 Hash Generator

Tue Dec 26, 2023 7:45 pm

Using API will not work in my case, because I want to write onvif-script for my camera, which may require generating many hashes per second
 
alexbayker
just joined
Posts: 4
Joined: Mon Dec 25, 2023 5:15 pm

Re: Script MD5 Hash Generator

Thu Feb 15, 2024 6:02 pm

This is my sha1 script for Mikrotik. I decided to take the trouble and write it. It works, but may need optimization

:global str2sha1 do={
	:local Debug 0

	:local strMessage [:tostr "$1"]
	
	:local arrCharSet ( "\00", "\01", "\02", "\03", "\04", "\05", "\06", "\07", \
						"\08", "\09", "\0A", "\0B", "\0C", "\0D", "\0E", "\0F", \
						"\10", "\11", "\12", "\13", "\14", "\15", "\16", "\17", \
						"\18", "\19", "\1A", "\1B", "\1C", "\1D", "\1E", "\1F", \
						"\20", "\21", "\22", "\23", "\24", "\25", "\26", "\27", \
						"\28", "\29", "\2A", "\2B", "\2C", "\2D", "\2E", "\2F", \
						"\30", "\31", "\32", "\33", "\34", "\35", "\36", "\37", \
						"\38", "\39", "\3A", "\3B", "\3C", "\3D", "\3E", "\3F", \
						"\40", "\41", "\42", "\43", "\44", "\45", "\46", "\47", \
						"\48", "\49", "\4A", "\4B", "\4C", "\4D", "\4E", "\4F", \
						"\50", "\51", "\52", "\53", "\54", "\55", "\56", "\57", \
						"\58", "\59", "\5A", "\5B", "\5C", "\5D", "\5E", "\5F", \
						"\60", "\61", "\62", "\63", "\64", "\65", "\66", "\67", \
						"\68", "\69", "\6A", "\6B", "\6C", "\6D", "\6E", "\6F", \
						"\70", "\71", "\72", "\73", "\74", "\75", "\76", "\77", \
						"\78", "\79", "\7A", "\7B", "\7C", "\7D", "\7E", "\7F"  )
						
	:local hexSymbSet "0123456789abcdef"

	:local h1   0x67452301
	:local h2   0xEFCDAB89
	:local h3   0x98BADCFE
	:local h4   0x10325476
	:local h5   0xC3D2E1F0
	:local k1   0x5A827999
	:local k2   0x6ED9EBA1
	:local k3   0x8F1BBCDC
	:local k4   0xCA62C1D6

	:local x40  0x40000000
	:local xF   0xF
	:local x100 0x100000000
	:local x7F  0x7FFFFFFF
	
	:local amp  0xFFFFFFFF
	
	:if ($Debug > 0) do={
		:put "Message: $strMessage"
	}
	
	:local messageLength [:len $strMessage]  
	
	:local binaryString ""
	:local binaryWOSpaces ""
	
	:local leftrotate 0
	:local left 0
	:local right 0
	
	:local start 0
	:local number 0
	
	:local b16 0
	:local b15 0
	:local b14 0
	:local b13 0
	:local b12 0
	:local b11 0
	:local b10 0
	:local b9  0
	:local b8  0
	:local b7  0
	:local b6  0
	:local b5  0
	:local b4  0
	:local b3  0
	:local b2  0
	:local b1  0
   
	:for i from 1 to=($messageLength) do={
		:set start (i - 1)
		:local char [:pick $strMessage $start $i]
		
		:set number [:find $arrCharSet $char]
		:set b8 0 ; :if ($number & 128) do={:set b8 1}
		:set b7 0 ; :if ($number &  64) do={:set b7 1}
		:set b6 0 ; :if ($number &  32) do={:set b6 1}
		:set b5 0 ; :if ($number &  16) do={:set b5 1}
		:set b4 0 ; :if ($number &   8) do={:set b4 1}
		:set b3 0 ; :if ($number &   4) do={:set b3 1}
		:set b2 0 ; :if ($number &   2) do={:set b2 1}
		:set b1 0 ; :if ($number &   1) do={:set b1 1}
		
		:local binaryChar "$b8$b7$b6$b5$b4$b3$b2$b1"
		
		:set binaryString "$binaryString $binaryChar"
		:set binaryWOSpaces "$binaryWOSpaces$binaryChar"
	}
	
	:local binaryLength [:len $binaryString]  
	
	:local binaryMessageLength ($messageLength * 8 - 8)
	:local bitLength ($binaryMessageLength + 8)
	
	:set number $bitLength
	:set b16 0 ; :if ($number & 32768) do={:set b16 1}
	:set b15 0 ; :if ($number & 16384) do={:set b15 1}
	:set b14 0 ; :if ($number &  8192) do={:set b14 1}
	:set b13 0 ; :if ($number &  4096) do={:set b13 1}
	:set b12 0 ; :if ($number &  2048) do={:set b12 1}
	:set b11 0 ; :if ($number &  1024) do={:set b11 1}
	:set b10 0 ; :if ($number &   512) do={:set b10 1}
	:set b9  0 ; :if ($number &   256) do={:set b9  1}
	:set b8  0 ; :if ($number &   128) do={:set b8  1}
	:set b7  0 ; :if ($number &    64) do={:set b7  1}
	:set b6  0 ; :if ($number &    32) do={:set b6  1}
	:set b5  0 ; :if ($number &    16) do={:set b5  1}
	:set b4  0 ; :if ($number &     8) do={:set b4  1}
	:set b3  0 ; :if ($number &     4) do={:set b3  1}
	:set b2  0 ; :if ($number &     2) do={:set b2  1}
	:set b1  0 ; :if ($number &     1) do={:set b1  1}
		
	:local endBitLength "$b16$b15$b14$b13$b12$b11$b10$b9$b8$b7$b6$b5$b4$b3$b2$b1"
	
	:for i from 1 to=(48) do={
		:set endBitLength "0$endBitLength"
	}
	
	:local subMod [:len $endBitLength]  
	
	:local binaryZeros ($binaryMessageLength % 512)
	
	:if ((432 - $binaryZeros) < 0) do={
		:local x (512 - $binaryZeros)
		:set binaryZeros ($x + 440 + $binaryZeros + 64)
	} else={
		:set binaryZeros (432 - $binaryZeros)
	}
	
	:local messageBinary ($binaryWOSpaces . "10000000")
	
	:while ($binaryZeros > 0) do={
		:set messageBinary ($messageBinary . "0")
		:set binaryZeros ($binaryZeros - 1)
	}
	
	:set messageBinary ($messageBinary . $endBitLength)
	
	:local mLength [:len $messageBinary]
	
	:local mArray []
	
	:local dec 0
	
	:for i from=0 to=($mLength - 1) step=32 do={
		:local subStr [:pick $messageBinary ($i + 1) ($i + 32)]
		
		:set dec 0
		
		:local subStrLen [:len $subStr]
		
		:for j from 1 to=($subStrLen) do={
			:set start (j - 1)
			:local char [:pick $subStr $start $j]
			:local num [:tonum $char]
			
			:set dec ($dec + ($num * (1 << ($subStrLen - $j))))
		}
	
		:set number $dec
		:local hexadec "0"
		:local remainder 0
		:if ($number > 0) do={:set hexadec ""}
		:while ( $number > 0 ) do={
			:set remainder ($number % 16)
			:set number (($number - $remainder) / 16)
			:set hexadec ([:pick $hexSymbSet $remainder] . $hexadec)
		} 
		:if ([:len $hexadec] = 1) do={:set hexadec "0$hexadec"}
		
		:local end (i + 1)
		:local startChar [:pick $messageBinary $i $end]
		:local charNum [:tonum $startChar]
		
		:local numInMArray [:tonum $hexadec]
		
		:if ($charNum = 1) do={
			:set numInMArray ($numInMArray | 0x80000000)
			:set dec (-1 * $numInMArray)
		}
		
		if ([:len $dec] > 0) do={
			:set ($mArray->($i / 32)) $dec
		}
		
		:if ($Debug > 0) do={
			:put ("Iteration: $i $subStr $dec")
		}
	}

	:local integerCount [:len $mArray]
	
	:local intArray []
	
	:local j 0
	
	:for i from 0 to=($integerCount - 1) step=16 do={
		:for j from 0 to=15 do={
			:set ($intArray->$j) ($mArray->($j + $i))
		}
		:for j from 16 to=79 do={
			:local x (($intArray->($j - 3)) ^ ($intArray->($j - 8)) ^ ($intArray->($j - 14)) ^ ($intArray->($j - 16)))
			:if ($x >= 0) do={
				:set leftrotate (((($x << 1) | (($x >> 31) )) & $amp ))
			} else={
				:set left ($x << 1)
				:set right ((((($x >> 1) & $x7F) | $x40) >> 30))
				:set leftrotate ((($left) | ($right)) & $amp )
			}
			:if ($leftrotate > $x7F) do={
				:set leftrotate ($leftrotate - $x100)
			}
			:set ($intArray->$j) $leftrotate
		}
		
		:local A $h1
		:local B $h2
		:local C $h3
		:local D $h4
		:local E $h5
		:local t 0
		
		:for x from 0  to=19 do={
			:if ($A >= 0) do={
				:set leftrotate ((($A << 5) | (($A >> 27) )) & $amp)
			} else={
				:set left ($A << 5)
				:set right ((((($A >> 1) & $x7F) | $x40) >> 26))
				:set leftrotate ((($left) | ($right)) & $amp )
			}
			:if ($leftrotate > $x7F) do={
				:set leftrotate ($leftrotate - $x100)
			}
			:local nB ((-1 - $B) & $amp)
			:local brackets (($B & $C) | ($nB & $D))
			:local fromArray ($intArray->($x))
			:set t (($leftrotate + $brackets + $E + $fromArray + $k1) & $amp)
			:if ($t > $x7F) do={
				:set t ($t - $x100)
			}
			:set E $D
			:set D $C
			:if ($B >= 0) do={
				:set C ((($B << 30) | (($B >> 2) )) & $amp )
			} else={
				:set left ($B << 30)
				:set right ((((($B >> 1) & $x7F) | $x40) >> 1))
				:set C ((($left) | ($right)) & $amp )
			}
			:if ($C > $x7F) do={
				:set C ($C - $x100)
			}
			:set B $A
			:set A $t
		}
		:for b from 20 to=39 do={
			:if ($A >= 0) do={
				:set leftrotate ((($A << 5) | (($A >> 27) )) & $amp)
			} else={
				:set left ($A << 5)
				:set right ((((($A >> 1) & $x7F) | $x40) >> 26))
				:set leftrotate ((($left) | ($right)) & $amp )
			}
			:if ($leftrotate > $x7F) do={
				:set leftrotate ($leftrotate - $x100)
			}
			:local brackets ($B ^ $C ^ $D)
			:local fromArray ($intArray->($b))
			:set t (($leftrotate + $brackets + $E + $fromArray + $k2) & $amp)
			:if ($t > $x7F) do={
				:set t ($t - $x100)
			}
			:set E $D
			:set D $C
			:if ($B >= 0) do={
				:set C ((($B << 30) | (($B >> 2) )) & $amp )
			} else={
				:set left ($B << 30)
				:set right ((((($B >> 1) & $x7F) | $x40) >> 1))
				:set C ((($left) | ($right)) & $amp )
			}
			:if ($C > $x7F) do={
				:set C ($C - $x100)
			}
			:set B $A
			:set A $t
		}
		:for c from 40 to=59 do={
			:if ($A >= 0) do={
				:set leftrotate ((($A << 5) | (($A >> 27) )) & $amp)
			} else={
				:set left ($A << 5)
				:set right ((((($A >> 1) & $x7F) | $x40) >> 26))
				:set leftrotate ((($left) | ($right)) & $amp )
			}
			:if ($leftrotate > $x7F) do={
				:set leftrotate ($leftrotate - $x100)
			}
			:local brackets (($B & $C) | ($B & $D) | ($C & $D))
			:local fromArray ($intArray->($c))
			:set t (($leftrotate + $brackets + $E + $fromArray + $k3)  & $amp)
			:if ($t > $x7F) do={
				:set t ($t - $x100)
			}
			:set E $D
			:set D $C
			:if ($B >= 0) do={
				:set C ((($B << 30) | (($B >> 2) )) & $amp )
			} else={
				:set left ($B << 30)
				:set right ((((($B >> 1) & $x7F) | $x40) >> 1))
				:set C ((($left) | ($right)) & $amp )
			}
			:if ($C > $x7F) do={
				:set C ($C - $x100)
			}
			:set B $A
			:set A $t
		}
		:for d from 60 to=79 do={
			:if ($A >= 0) do={
				:set leftrotate ((($A << 5) | (($A >> 27) )) & $amp)
			} else={
				:set left ($A << 5)
				:set right ((((($A >> 1) & $x7F) | $x40) >> 26))
				:set leftrotate ((($left) | ($right)) & $amp )
			}
			:if ($leftrotate > $x7F) do={
				:set leftrotate ($leftrotate - $x100)
			}
			:local brackets ($B ^ $C ^ $D)
			:local fromArray ($intArray->($d))
			:set t (($leftrotate + $brackets + $E + $fromArray + $k4) & $amp)
			:if ($t > $x7F) do={
				:set t ($t - $x100)
			}
			:set E $D
			:set D $C
			:if ($B >= 0) do={
				:set C ((($B << 30) | (($B >> 2) )) & $amp )
			} else={
				:set left ($B << 30)
				:set right ((((($B >> 1) & $x7F) | $x40) >> 1))
				:set C ((($left) | ($right)) & $amp )
			}
			:if ($C > $x7F) do={
				:set C ($C - $x100)
			}
			:set B $A
			:set A $t
		}
		
		:set h1 (($h1 + $A) & $amp )
		:if ($h1 > $x7F) do={
			:set h1 ($h1 - $x100)
		}
		:set h2 (($h2 + $B) & $amp )
		:if ($h2 > $x7F) do={
			:set h2 ($h2 - $x100)
		}
		:set h3 (($h3 + $C) & $amp )
		:if ($h3 > $x7F) do={
			:set h3 ($h3 - $x100)
		}
		:set h4 (($h4 + $D) & $amp )
		:if ($h4 > $x7F) do={
			:set h4 ($h4 - $x100)
		}
		:set h5 (($h5 + $E) & $amp ) 
		:if ($h5 > $x7F) do={
			:set h5 ($h5 - $x100)
		}
	}
	:if ($Debug > 0) do={
		:put ("This is h: $h1 $h2 $h3 $h4 $h5")
	}

	:local hexdigit 8
	:local hex1 ""
	:local hex2 ""
	:local hex3 ""
	:local hex4 ""
	:local hex5 ""
	
	:for i from=0 to=(4 * ($hexdigit - 1)) step=4 do={ 
		:set hex1 ([:pick $hexSymbSet (($h1 >> $i) & $xF) ((($h1 >> $i) & $xF) + 1)] . $hex1)
	}
	
	:set hexdigit 8
	:for i from=0 to=(4 * ($hexdigit - 1)) step=4 do={ 
		:set hex2 ([:pick $hexSymbSet (($h2 >> $i) & $xF) ((($h2 >> $i) & $xF) + 1)] . $hex2)
	}
	
	:set hexdigit 8
	:for i from=0 to=(4 * ($hexdigit - 1)) step=4 do={ 
		:set hex3 ([:pick $hexSymbSet (($h3 >> $i) & $xF) ((($h3 >> $i) & $xF) + 1)] . $hex3)
	}
	
	:set hexdigit 8
	:for i from=0 to=(4 * ($hexdigit - 1)) step=4 do={ 
		:set hex4 ([:pick $hexSymbSet (($h4 >> $i) & $xF) ((($h4 >> $i) & $xF) + 1)] . $hex4)
	}
	
	:set hexdigit 8
	:for i from=0 to=(4 * ($hexdigit - 1)) step=4 do={ 
		:set hex5 ([:pick $hexSymbSet (($h5 >> $i) & $xF) ((($h5 >> $i) & $xF) + 1)] . $hex5)
	}
	
	:local result "$hex1$hex2$hex3$hex4$hex5"
	
	:if ($Debug > 0) do={
		:put ("THIS IS HEX: $hex1 $hex2 $hex3 $hex4 $hex5")
		:put ("MArray  Length: $integerCount")
		:put ("Message Length: $binaryString $binaryLength")
		:put ("End bit Length: $endBitLength $binaryZeros")
		:put ("Message Binary: $messageBinary $mLength")
		:put ("THIS IS RESULT: $result")
	}
	
	:return $result;
} 

You can run it like this:

/system script run str2sha1
:global str2sha1;

:local answer [$str2sha1 "This is text for sha1 in RouterOS"];
:put "this is result $answer"
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Script MD5 Hash Generator

Thu Feb 15, 2024 9:52 pm

Thanks for sharing,
There are very few errors, and the writing style is acceptable.

I like that you are inspired from my scripts...
viewtopic.php?t=177551#p965201

just at the start...
:local strMessage [:tostr "$1"]
is like
:local strMessage [:tostr [:tostr $1 ]]
so, why not simply
:local strMessage [:tostr $1]
?

missing all 0x80..0xFF characters...

chr2int is simpler for convert character to decimal
viewtopic.php?t=191609#p971663
dec2bin is faster and more easy for convert number to binary
viewtopic.php?t=177551#p967775

using both as base, this create one array on memory for all 255 possible values already calculated, is faster than do everytime all the opreation for each single characters:

Array of Characters to Binary code

:global charsString ""
:for x from=0 to=15 step=1 do={ :for y from=0 to=15 step=1 do={
    :local tmpHex "$[:pick "0123456789ABCDEF" $x ($x+1)]$[:pick "0123456789ABCDEF" $y ($y+1)]"
    :set $charsString "$charsString$[[:parse "(\"\\$tmpHex\")"]]"
} }

:global dec2bin do={
    :local number [:tonum $1]
    :local ret    ""
    :local rshift 7
    :if ($number >       0xFF) do={:set rshift 15}
    :if ($number >     0xFFFF) do={:set rshift 31}
    :if ($number > 0xFFFFFFFF) do={:set rshift 63}
    :for i from=0 to=$rshift step=1 do={
        :set ret "$(($number >> $i) & 1)$ret"
    }
    :return $ret
}

:global arrCharBin [:toarray ""]
:for x from=0 to=255 step=1 do={
    :set ($arrCharBin->[:pick $charsString $x ($x + 1)]) [$dec2bin $x]
}

for convert a character, simply get the keyed value on the array with same name as the character...

terminal code

[rex@home] > :put ($arrCharBin->"v")  
01110110
[rex@home] > :put ($arrCharBin->"i") 
01101001
[rex@home] > :put ($arrCharBin->"v") 
01110110
[rex@home] > :put ($arrCharBin->"a") 
01100001
[rex@home] > :put ($arrCharBin->"l") 
01101100
[rex@home] > :put ($arrCharBin->"a") 
01100001
[rex@home] > :put ($arrCharBin->"f") 
01100110
[rex@home] > :put ($arrCharBin->"c") 
01100011
[rex@home] > :put ($arrCharBin->"a") 
01100001
[rex@home] > 

Who is online

Users browsing this forum: rogerioqueiroz and 21 guests