Fritzbox Login via URL - MD5 Hash

  • Hallo, ich habe im Inet Folgendes SH Script gefunden und würde dieses gerne in Autoit Realisieren.

    Spoiler anzeigen

    #!/bin/sh

    # Challenge abholen
    ChallengeXML=`wget -O - "http://fritz.box/cgi-bin/webcm?getpage=../html/login_sid.xml" 2>/dev/null| grep Challenge`
    Challenge=`echo $ChallengeXML | awk '{match($0,/>[^<>]+</); print substr($0,RSTART+1,RLENGTH-2)}'`

    Passwd="xxxxx"

    # login aufbauen und hashen
    CPSTR="$Challenge-$Passwd"
    MD5=`echo -n $CPSTR | iconv -f ISO8859-1 -t UTF-16LE | md5sum -b | awk '{print substr($0,1,32)}'`
    RESPONSE="$Challenge-$MD5"
    POSTDATA="login:command/response=$RESPONSE&getpage=../html/de/menus/menu2.html"

    # login senden und SID herausfischen
    SID=`wget -O - --post-data="$POSTDATA" "http://fritz.box/cgi-bin/webcm" 2>/dev/null| grep "name=\"sid\"" | head -1 | awk '{match($0,/value="[^"]+"/); print substr($0,RSTART+7,RLENGTH-8)}'`

    # refresh der daten auslösen
    wget -O /dev/null "http://fritz.box//cgi-bin/webcm?sid=$SID&getpage=../html/de/menus/menu2.html&errorpage=../html/de/menus/menu2.html&var:pagename=foncalls&var:errorpagename=foncalls&var:menu=home&var:pagemaster=&var:activtype=pppoe&var:tabInetstat=0&var:weckernr=&logger:settings/filter=2"

    # CSV runterladen
    wget -O ../fb_anrufliste.csv "http://fritz.box/cgi-bin/webcm?sid=$SID&getpage=../html/de/FRITZ!Box_Anrufliste.csv" 2>/dev/null

    [autoit][/autoit][autoit][/autoit][autoit]

    #include <http.au3>
    #include <MD5.au3>

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    $host = "fritz.box"
    $Fritzpass = "XXXXXXXXX"
    $Challenge=StringRegExp(_INetGetSource("http://fritz.box/cgi-bin/webcm?getpage=../html/login_sid.xml"),"<Challenge>(.*)</Challenge>",1)
    $Challenge=$Challenge[0]
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $Challenge = ' & $Challenge & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    $CPSTR=$Challenge & "-" & $Fritzpass
    $MD5 = md5($CPSTR)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $MD5 = ' & $MD5 & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    $RESPONSE = $Challenge & "-" & $MD5
    $POSTDATA="login:command/response=" & $RESPONSE & "&getpage=../html/de/menus/menu2.html"
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $POSTDATA = ' & $POSTDATA & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    $httpsocet = _HTTPConnect($host)
    $RC = _HTTPPost($host, "http://" & $host & "/cgi-bin/webcm", $httpsocet,$POSTDATA)
    sleep(1000)
    $RC = _HTTPRead($httpsocet,0)
    $SID = StringRegExp($RC,'[nNaAmMeE]+="[sSiIdD]+"\s*[vVaAlLuUeE]+\s*=\s*"(.*)"\s+',1)
    $SID = $SID[0]
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $SID = ' & $SID & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    $ErrorMessage = StringRegExp($RC,'errorMessage">(.*)<',1)
    $ErrorMessage = $ErrorMessage[0]
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ErrorMessage = ' & $ErrorMessage & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

    [/autoit][autoit][/autoit][autoit]

    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $RC = ' & $RC & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

    [/autoit]

    Nur leider bekomme ich immer nur Passwort Falsch ich denke irgendwas hab ich mit dem MD5 hash falsch gemacht.
    Kann mir einer Helfen?

    Edit: ich glaube ich habe es gefunden ich brauche eine Convertierung von ISO8859-1 UTF-16LE damit sollte es funktionieren wie kann ich den String in Autoit auf die Entsprechenden Formate Convertirern?
    unter Linux get es mit "iconv -f ISO8859-1 -t UTF-16LE"

    http.au3

    Spoiler anzeigen
    [autoit]

    ; ===================================================================
    ; HTTP UDF's
    ; v0.5
    ;
    ; By: Greg "Overload" Laabs
    ; Last Updated: 07-22-06
    ; Tested with AutoIt Version 3.1.1.131
    ; Extra requirements: Nothing!
    ;
    ; A set of functions that allow you to download webpages and submit
    ; POST requests.
    ;
    ; Main functions:
    ; _HTTPConnect - Connects to a webserver
    ; _HTTPGet - Submits a GET request to a webserver
    ; _HTTPPost - Submits a POST request to a webserver
    ; _HTTPRead - Reads the response from a webserver
    ; ===================================================================

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    TCPStartup()

    [/autoit] [autoit][/autoit] [autoit]

    Global $_HTTPUserAgent = "AutoItScript/"&@AutoItVersion
    Global $_HTTPLastSocket = -1
    Global $_HTTPRecvTimeout = 30000

    [/autoit] [autoit][/autoit] [autoit]

    ; ===================================================================
    ; _HTTPSetUserAgent($Program, $Version)
    ;
    ; Sets the User-Agent that will be sent with all future _HTTP
    ; functions. If this is never called, the user agent is set to
    ; AutoItScript/[YourAutoItVersion]
    ; Parameters:
    ;$Program - IN - The name of the program
    ;$Version - IN - The version number of the program
    ; Returns:
    ;None
    ; ===================================================================
    Func _HTTPSetUserAgent($Program, $Version)
    $_HTTPUserAgent = $Program&"/"&$Version
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; ===================================================================
    ; _HTTPConnect($host, [$port])
    ;
    ; Opens a connection to $host on the port you supply (or 80 if you don't supply a port. Returns the socket of the connection.
    ; Parameters:
    ;$host - IN - The hostname you want to connect to. This should be in the format "www.google.com" or "localhost"
    ;$port - OPTIONAL IN - The port to connect on. 80 is default.
    ; Returns:
    ;The socket of the connection.
    ; Remarks:
    ; Possible @errors:
    ; 1 - Unable to open socket - @extended is set to Windows API WSAGetLasterror return
    ; ===================================================================
    Func _HTTPConnect($host, $port = 80)
    Dim $ip = TCPNameToIP ( $host )
    Dim $socket = TCPConnect ( $ip, 80 )

    [/autoit] [autoit][/autoit] [autoit]

    If ($socket == -1) Then
    SetError(1, @error)
    Return -1
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    $_HTTPLastSocket = $socket
    SetError(0)
    Return $socket
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; Possible @errors:
    ; 1 - No socket
    Func _HTTPClose($socket = -1)
    If $socket == -1 Then
    If $_HTTPLastSocket == -1 Then
    SetError(1)
    Return 0
    EndIf
    $socket = $_HTTPLastSocket
    EndIf
    TCPCloseSocket($socket)

    [/autoit] [autoit][/autoit] [autoit]

    SetError(0)
    Return 1
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; ===================================================================
    ; _HTTPGet($host, $page, [$socket])
    ;
    ; Executes a GET request on an open socket.
    ; Parameters:
    ;$host - IN - The hostname you want to get the page from. This should be in the format "www.google.com" or "localhost"
    ;$page - IN - The the file you want to get. This should always start with a slash. Examples: "/somepage.php" or "/somedirectory/somefile.zip"
    ;$socket - OPTIONAL IN - The socket opened by _HTTPConnect. If this is not supplied, the last socket opened with _HTTPConnect will be used.
    ; Returns:
    ;The number of bytes sent in the request.
    ; Remarks:
    ; Possible @errors:
    ; 1 - No socket supplied and no current socket exists
    ; 2 - Error sending to socket. Check @extended for Windows API WSAGetError return
    ; ===================================================================
    Func _HTTPGet($host, $page, $socket = -1)
    Dim $command

    [/autoit] [autoit][/autoit] [autoit]

    If $socket == -1 Then
    If $_HTTPLastSocket == -1 Then
    SetError(1)
    Return
    EndIf
    $socket = $_HTTPLastSocket
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    $command = "GET "&$page&" HTTP/1.1"&@CRLF
    $command &= "Host: " &$host&@CRLF
    $command &= "User-Agent: "&$_HTTPUserAgent&@CRLF
    $command &= "Connection: close"&@CRLF
    $command &= ""&@CRLF

    [/autoit] [autoit][/autoit] [autoit]

    Dim $bytessent = TCPSend($socket, $command)

    [/autoit] [autoit][/autoit] [autoit]

    If $bytessent == 0 Then
    SetExtended(@error)
    SetError(2)
    return 0
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    SetError(0)
    Return $bytessent
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; ===================================================================
    ; _HTTPPost($host, $page, [$socket])
    ;
    ; Executes a POST request on an open socket.
    ; Parameters:
    ;$host - IN - The hostname you want to get the page from. This should be in the format "www.google.com" or "localhost"
    ;$page - IN - The the file you want to get. This should always start with a slash. Examples: "/" or "/somedirectory/submitform.php"
    ;$socket - OPTIONAL IN - The socket opened by _HTTPConnect. If this is not supplied, the last socket opened with _HTTPConnect will be used.
    ;$data - OPTIONAL IN - The data to send in the post request. This should first be run through _HTTPEncodeString()
    ; Returns:
    ;The number of bytes sent in the request.
    ; Remarks:
    ; Possible @errors:
    ; 1 - No socket supplied and no current socket exists
    ; 2 - Error sending to socket. Check @extended for Windows API WSAGetError return
    ; ===================================================================
    Func _HTTPPost($host, $page, $socket = -1, $data = "")
    Dim $command

    [/autoit] [autoit][/autoit] [autoit]

    If $socket == -1 Then
    If $_HTTPLastSocket == -1 Then
    SetError(1)
    Return
    EndIf
    $socket = $_HTTPLastSocket
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    Dim $datasize = StringLen($data)

    [/autoit] [autoit][/autoit] [autoit]

    $command = "POST "&$page&" HTTP/1.1"&@CRLF
    $command &= "Host: " &$host&@CRLF
    $command &= "User-Agent: "&$_HTTPUserAgent&@CRLF
    $command &= "Connection: close"&@CRLF
    $command &= "Content-Type: application/x-www-form-urlencoded"&@CRLF
    $command &= "Content-Length: "&$datasize&@CRLF
    $command &= ""&@CRLF
    $command &= $data&@CRLF

    [/autoit] [autoit][/autoit] [autoit]

    Dim $bytessent = TCPSend($socket, $command)

    [/autoit] [autoit][/autoit] [autoit]

    If $bytessent == 0 Then
    SetExtended(@error)
    SetError(2)
    return 0
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    SetError(0)
    Return $bytessent
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; ===================================================================
    ; _HTTPRead([$socket], [$flag])
    ;
    ; Retrieves data from an open socket. This should only be called after _HTTPGet or _HTTPPost is called.
    ; Parameters:
    ;$socket - OPTIONAL IN - The socket you want to receive data from. If this is not supplied, the last socket opened with _HTTPConnect will be used.
    ;$flag - OPTIONAL IN - Determines how the data will be returned. See Remarks.
    ; Returns:
    ;See "Flags" in remarks, below.
    ; Remarks:
    ; Possible @errors:
    ; 1 - No socket
    ; 3 - Timeout reached before any data came through the socket
    ; 4 - Some data came through, but not all of it. Return value is the number of bytes received.
    ; 5 - Unable to parse HTTP Response from server. Return value is the HTTP Response line
    ; 6 - Unexpected header data returned. Return value is the line that caused the error
    ; 7 - Invalid flag
    ; 8 - Unable to parse chunk size. Return value is the line that caused the error
    ; Flags:
    ; 0 - Return value is the body of the page (default)
    ; 1 - Return value is an array:
    ; [0] = HTTP Return Code
    ; [1] = HTTP Return Reason (human readable return code like "OK" or "Forbidden"
    ; [2] = HTTP Version
    ; [3] = Two dimensional array with the headers. Each item has:
    ; [0] = Header name
    ; [1] = Header value
    ; [4] = The body of the page
    ; ===================================================================
    Func _HTTPRead($socket = -1, $flag = 0)
    If $socket == -1 Then
    If $_HTTPLastSocket == -1 Then
    SetError(1)
    Return
    EndIf
    $socket = $_HTTPLastSocket
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    Dim $timer = TimerInit()
    Dim $performancetimer = TimerInit()
    Dim $downloadtime = 0

    [/autoit] [autoit][/autoit] [autoit]

    Dim $headers[1][2] ; An Array of the headers found
    Dim $numheaders = 0 ; The number of headers found
    Dim $body = "" ; The body of the message
    Dim $HTTPVersion ; The HTTP version of the server (almost always 1.1)
    Dim $HTTPResponseCode ; The HTTP response code like 200, or 404
    Dim $HTTPResponseReason ; The human-readable response reason, like "OK" or "Not Found"
    Dim $bytesreceived = 0 ; The total number of bytes received
    Dim $data = "" ; The entire raw message gets put in here.
    Dim $chunked = 0 ; Set to 1 if we get the "Transfer-Encoding: chunked" header.
    Dim $chunksize = 0 ; The size of the current chunk we are processing.
    Dim $chunkprocessed = 0 ; The amount of data we have processed on the current chunk.
    Dim $contentlength ; The size of the body, if NOT using chunked transfer mode.
    Dim $part = 0 ; Refers to what part of the data we're currently parsing:
    ; 0 - Nothing parsed, so HTTP response should come next
    ; 1 - Currently parsing headers
    ; 2 - Currently waiting for the next chunk size - this is skipped if the transfer-encoding is not chunked
    ; 3 - Currently waiting for or parsing body data
    ; 4 - Currently parsing footers
    ;While 1
    Sleep(10)
    Dim $recv = TCPRecv($socket,16)
    If @error <> 0 Then
    ;ConsoleWrite("Server closed connection")
    ;@error appears to be -1 after the server closes the connection. A good way to tell that we're finished, because we always send
    ;the "Connection: close" header to the server.
    ; !!! This is no longer used because we can now tell that we're done by checking the content-length header or properly handling
    ; chunked data.
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    While $recv <> ""
    ;If $recv <> "" Then
    $bytesreceived = $bytesreceived + StringLen($recv)
    $timer = TimerInit()
    $data &= $recv
    ;ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $data = ' & $data & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    ;ConsoleWrite("Bytes downloaded: "&$bytesreceived&@CRLF)
    ;EndIf
    $recv = TCPRecv($socket,2048)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Dim $split = StringSplit($data,@CRLF,1)
    $data = ""
    Dim $i
    For $i=1 To $split[0]
    If $i=$split[0] Then
    If $part < 2 OR $chunked = 1 Then
    ; This is tricky. The last line we've received might be truncated, so we only want to process it under special cases.
    ; Non chunked data doesn't always send a CRLF at the end so there's no way to tell if this is truly the last line without parsing it.
    ; However, we don't want to parse it if it's only a partial header or something.
    ; The solution: We will only process this last line if we're at the body section and the transfer-encoding is NOT chunked.
    $data = $split[$i]
    ExitLoop
    EndIf
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    Dim $newpart = $part
    Switch $part
    Case 0 ; Nothing parsed, so HTTP response should come next
    If $split[$i] <> "" Then
    Dim $regex = StringRegExp($split[$i],"^HTTP/([0-9.]+) ([0-9]+) ([a-zA-Z0-9 ]+)$",3)
    If @error <> 0 Then
    SetError(5)
    Return $split[$i]
    Else
    $HTTPVersion = $regex[0]
    $HTTPResponseCode = $regex[1]
    $HTTPResponseReason = $regex[2]
    If $HTTPResponseCode <> 100 Then
    $newpart = 1
    EndIf
    EndIf
    EndIf
    Case 1, 4 ; Currently parsing headers or footers
    ;If the line is blank, then we're done with headers and the body is next
    If $split[$i] == "" Then
    If $part = 1 Then
    If $chunked Then
    $newpart = 2
    Else
    $newpart = 3
    EndIf
    ElseIf $part = 4 Then
    ; If $part is 4 then we're processing footers, so we're all done now.
    ExitLoop 2
    EndIf
    Else ;The line wasn't blank
    ;Check to see if the line begins with whitespace. If it does, it's actually
    ;a continuation of the previous header
    Dim $regex = StringRegExp($split[$i], "^[ \t]+([^ \t].*)$", 3)
    If @error <> 1 Then
    If $numheaders == 0 Then
    SetError(6)
    Return $split[$i]
    EndIf
    $headers[$numheaders-1][1] &= $regex[0]
    Else;The line didn't start with a space
    Dim $regex = StringRegExp($split[$i],"^([^ :]+):[ \t]*(.*)$",3)
    If @error <> 1 Then
    ;This is a new header, so add it to the array
    $numheaders = $numheaders + 1
    ReDim $headers[$numheaders][2]
    $headers[$numheaders-1][0] = $regex[0]
    $headers[$numheaders-1][1] = $regex[1]

    [/autoit] [autoit][/autoit] [autoit]

    ; There are a couple headers we need to know about. We'll process them here.
    If $regex[0] = "Transfer-Encoding" AND $regex[1] = "chunked" Then
    $chunked = 1
    ElseIf $regex[0] = "Content-Length" Then
    $contentlength = Int($regex[1])
    EndIf
    Else
    SetError(6)
    Return $split[$i]
    EndIf
    EndIf
    EndIf
    Case 2 ; Awaiting chunk size
    $regex = StringRegExp($split[$i],"^([0-9a-f]+);?.*$",3)
    If @error <> 0 Then
    SetError(8)
    Return $split[$i]
    EndIf
    $chunksize = $regex[0]
    $chunksize = Dec($chunksize)
    $chunkprocessed = 0

    [/autoit] [autoit][/autoit] [autoit]

    If $chunksize == 0 Then
    $newpart = 4
    Else
    $newpart = 3
    EndIf
    Case 3 ; Awaiting body data
    $body &= $split[$i]

    [/autoit] [autoit][/autoit] [autoit]

    $chunkprocessed = $chunkprocessed + StringLen($split[$i])

    [/autoit] [autoit][/autoit] [autoit]

    If $chunked Then
    If $chunkprocessed >= $chunksize Then
    $newpart = 2
    Else
    $body &= @CRLF
    $chunkprocessed = $chunkprocessed + 2; We add 2 for the CRLF we stipped off.
    EndIf
    Else
    If not $chunkprocessed >= $contentlength Then
    If $i < $split[0] Then
    ; Only add a CRLF if this is not the last line received.
    $body &= @CRLF
    $chunkprocessed = $chunkprocessed + 2; We add 2 for the CRLF we stipped off.
    EndIf
    EndIf
    EndIf
    Case Else
    ; This should never happen
    EndSwitch
    $part = $newpart
    Next

    [/autoit] [autoit][/autoit] [autoit]

    If $bytesreceived == 0 AND TimerDiff($timer) > $_HTTPRecvTimeout Then
    SetError(3)
    Return 0
    ElseIf $bytesreceived > 0 AND TimerDiff($timer) > $_HTTPRecvTimeout Then
    ConsoleWrite($body)
    SetError(4)
    Return $bytesreceived
    EndIf
    ;WEnd
    $downloadtime = TimerDiff($performancetimer)
    ;ConsoleWrite("Performance: Download time: "&$downloadtime&@CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    Switch $flag
    Case 0
    SetError(0)
    Return $body
    Case 1
    Dim $return[5]
    $return[0] = $HTTPResponseCode
    $return[1] = $HTTPResponseReason
    $return[2] = $HTTPVersion
    $return[3] = $headers
    $return[4] = $body
    SetError(0)
    Return $return
    Case Else
    SetError(7)
    Return 0
    EndSwitch
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; ===================================================================
    ; _HTTPEncodeString($string)
    ;
    ; Encodes a string so it can safely be transmitted via HTTP
    ; Parameters:
    ;$string - IN - The string to encode
    ; Returns:
    ;A valid encoded string that can be used as GET or POST variables.
    ; ===================================================================
    Func _HTTPEncodeString($string)
    Local Const $aURIValidChars[256] = _
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _
    0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, _
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, _
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, _
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

    [/autoit] [autoit][/autoit] [autoit]

    Local $sEncoded = ""
    For $i = 1 To StringLen($string)
    Local $c = StringMid($string, $i, 1)
    If $c = " " Then $c = "+"
    If Number($aURIValidChars[Asc($c) ]) Then
    $sEncoded &= $c
    Else
    $sEncoded &= StringFormat("%%X", Asc($c))
    EndIf
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Return $sEncoded
    EndFunc ;==>_WebComposeURL

    [/autoit]

    MD5.au3

    Spoiler anzeigen
    [autoit]


    ; Converted to AutoIt script by SvenP

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; MODULE: CMD5
    ; FILENAME: C:\My Code\vb\md5\CMD5.cls
    ; AUTHOR: Phil Fresle
    ; CREATED: 16-Feb-2001
    ; COPYRIGHT:Copyright 2001 Frez Systems Limited. All Rights Reserved.
    ;
    ; DESCRIPTION:
    ; Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm,
    ; as set out in the memo RFC1321.
    ;
    ; This class is used to generate an MD5 ;digest; or ;signature; of a string. The
    ; MD5 algorithm is one of the industry standard methods for generating digital
    ; signatures. It is generically known as a digest, digital signature, one-way
    ; encryption, hash or checksum algorithm. A common use for MD5 is for password
    ; encryption as it is one-way in nature, that does not mean that your passwords
    ; are not free from a dictionary attack. If you are using the
    ; routine for passwords, you can make it a little more secure by concatenating
    ; some known random characters to the password before you generate the signature
    ; and on Funcsequent tests, so even if a hacker knows you are using MD5 for
    ; your passwords, the random characters will make it harder to dictionary attack.
    ;
    ; *** CAUTION ***
    ; See the comment attached to the MD5 method below regarding use on systems
    ; with different character sets.
    ;
    ; This is 'free' software with the following restrictions:
    ;
    ; You may not redistribute this code as a 'sample'or 'demo'. However, you are free
    ; to use the source code in your own code, but you may not claim that you created
    ; the sample code. It is expressly forbidden to sell or profit from this source code
    ; other than by the knowledge gained or the enhanced value added by your own code.
    ;
    ; Use of this software is also done so at your own risk. The code is supplied as
    ; is without warranty or guarantee of any kind.
    ;
    ; Should you wish to commission some derivative work based on this code provided
    ; here, or any consultancy work, please do not hesitate to contact us.
    ;
    ; Web Site: http://www.frez.co.uk
    ; E-mail:sales@frez.co.uk
    ;
    ; MODIFICATION HISTORY:
    ; 1.0 16-Feb-2001
    ; Phil Fresle
    ; Initial Version
    ;*******************************************************************************

    [/autoit] [autoit][/autoit] [autoit]

    Const $BITS_TO_A_BYTE = 8
    Const $BYTES_TO_A_WORD = 4
    Const $BITS_TO_A_WORD = $BYTES_TO_A_WORD * $BITS_TO_A_BYTE

    [/autoit] [autoit][/autoit] [autoit]

    Dim $m_lOnBits[31]
    Dim $m_l2Power[31]

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; Class_Initialize (Func)
    ;
    ; DESCRIPTION:
    ; We will usually get quicker results by preparing arrays of bit patterns and
    ; powers of 2 ahead of time instead of calculating them every time, unless of
    ; course the methods are only ever getting called once per instantiation of the
    ; class.
    ;*******************************************************************************
    Func Class_Initialize()
    ; Could have done this with a loop calculating each value, but simply
    ; assigning the values is quicker - BITS SET FROM RIGHT
    $m_lOnBits[0] = 1 ; 00000000000000000000000000000001
    $m_lOnBits[1] = 3 ; 00000000000000000000000000000011
    $m_lOnBits[2] = 7 ; 00000000000000000000000000000111
    $m_lOnBits[3] = 15 ; 00000000000000000000000000001111
    $m_lOnBits[4] = 31 ; 00000000000000000000000000011111
    $m_lOnBits[5] = 63 ; 00000000000000000000000000111111
    $m_lOnBits[6] = 127 ; 00000000000000000000000001111111
    $m_lOnBits[7] = 255 ; 00000000000000000000000011111111
    $m_lOnBits[8] = 511 ; 00000000000000000000000111111111
    $m_lOnBits[9] = 1023 ; 00000000000000000000001111111111
    $m_lOnBits[10] = 2047 ; 00000000000000000000011111111111
    $m_lOnBits[11] = 4095 ; 00000000000000000000111111111111
    $m_lOnBits[12] = 8191 ; 00000000000000000001111111111111
    $m_lOnBits[13] = 16383 ; 00000000000000000011111111111111
    $m_lOnBits[14] = 32767 ; 00000000000000000111111111111111
    $m_lOnBits[15] = 65535 ; 00000000000000001111111111111111
    $m_lOnBits[16] = 131071 ; 00000000000000011111111111111111
    $m_lOnBits[17] = 262143 ; 00000000000000111111111111111111
    $m_lOnBits[18] = 524287 ; 00000000000001111111111111111111
    $m_lOnBits[19] = 1048575 ; 00000000000011111111111111111111
    $m_lOnBits[20] = 2097151 ; 00000000000111111111111111111111
    $m_lOnBits[21] = 4194303 ; 00000000001111111111111111111111
    $m_lOnBits[22] = 8388607 ; 00000000011111111111111111111111
    $m_lOnBits[23] = 16777215; 00000000111111111111111111111111
    $m_lOnBits[24] = 33554431; 00000001111111111111111111111111
    $m_lOnBits[25] = 67108863; 00000011111111111111111111111111
    $m_lOnBits[26] = 134217727 ; 00000111111111111111111111111111
    $m_lOnBits[27] = 268435455 ; 00001111111111111111111111111111
    $m_lOnBits[28] = 536870911 ; 00011111111111111111111111111111
    $m_lOnBits[29] = 1073741823 ; 00111111111111111111111111111111
    $m_lOnBits[30] = 2147483647 ; 01111111111111111111111111111111

    [/autoit] [autoit][/autoit] [autoit]

    ; Could have done this with a loop calculating each value, but simply
    ; assigning the values is quicker - POWERS OF 2
    $m_l2Power[0] = 1 ; 00000000000000000000000000000001
    $m_l2Power[1] = 2 ; 00000000000000000000000000000010
    $m_l2Power[2] = 4 ; 00000000000000000000000000000100
    $m_l2Power[3] = 8 ; 00000000000000000000000000001000
    $m_l2Power[4] = 16 ; 00000000000000000000000000010000
    $m_l2Power[5] = 32 ; 00000000000000000000000000100000
    $m_l2Power[6] = 64 ; 00000000000000000000000001000000
    $m_l2Power[7] = 128 ; 00000000000000000000000010000000
    $m_l2Power[8] = 256 ; 00000000000000000000000100000000
    $m_l2Power[9] = 512 ; 00000000000000000000001000000000
    $m_l2Power[10] = 1024 ; 00000000000000000000010000000000
    $m_l2Power[11] = 2048 ; 00000000000000000000100000000000
    $m_l2Power[12] = 4096 ; 00000000000000000001000000000000
    $m_l2Power[13] = 8192 ; 00000000000000000010000000000000
    $m_l2Power[14] = 16384 ; 00000000000000000100000000000000
    $m_l2Power[15] = 32768 ; 00000000000000001000000000000000
    $m_l2Power[16] = 65536 ; 00000000000000010000000000000000
    $m_l2Power[17] = 131072 ; 00000000000000100000000000000000
    $m_l2Power[18] = 262144 ; 00000000000001000000000000000000
    $m_l2Power[19] = 524288 ; 00000000000010000000000000000000
    $m_l2Power[20] = 1048576 ; 00000000000100000000000000000000
    $m_l2Power[21] = 2097152 ; 00000000001000000000000000000000
    $m_l2Power[22] = 4194304 ; 00000000010000000000000000000000
    $m_l2Power[23] = 8388608 ; 00000000100000000000000000000000
    $m_l2Power[24] = 16777216; 00000001000000000000000000000000
    $m_l2Power[25] = 33554432; 00000010000000000000000000000000
    $m_l2Power[26] = 67108864; 00000100000000000000000000000000
    $m_l2Power[27] = 134217728 ; 00001000000000000000000000000000
    $m_l2Power[28] = 268435456 ; 00010000000000000000000000000000
    $m_l2Power[29] = 536870912 ; 00100000000000000000000000000000
    $m_l2Power[30] = 1073741824 ; 01000000000000000000000000000000
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; LShift (FUNCTION)
    ;
    ; PARAMETERS:
    ; (In) - $lValue - Long- The value to be shifted
    ; (In) - $iShiftBits - Integer - The number of bits to shift the value by
    ;
    ; RETURN VALUE:
    ; Long - The shifted long integer
    ;
    ; DESCRIPTION:
    ; A left shift takes all the set binary bits and moves them left, in-filling
    ; with zeros in the vacated bits on the right. This function is equivalent to
    ; the << operator in Java and C++
    ;*******************************************************************************
    Func LShift($lValue, $iShiftBits)
    ; NOTE: If you can guarantee that the Shift parameter will be in the
    ; range 1 to 30 you can safely strip of this first nested if structure for
    ; speed.
    ;
    ; A shift of zero is no shift at all.
    If $iShiftBits = 0 Then
    Return $lValue


    ; A shift of 31 will result in the right most bit becoming the left most
    ; bit and all other bits being cleared
    ElseIf $iShiftBits = 31 Then
    If BitAND($lValue, 1) Then
    Return 0x80000000
    Else
    Return 0
    Endif


    ; A shift of less than zero or more than 31 is undefined
    ElseIf $iShiftBits < 0 Or $iShiftBits > 31 Then
    SetError(6)
    Endif

    [/autoit] [autoit][/autoit] [autoit]

    ; If the left most bit that remains will end up in the negative bit
    ; position (0x80000000) we would end up with an overflow if we took the
    ; standard route. We need to strip the left most bit and add it back
    ; afterwards.
    If BitAND($lValue, $m_l2Power[31 - $iShiftBits]) Then

    [/autoit] [autoit][/autoit] [autoit]

    ; (Value And OnBits(31 - (Shift + 1))) chops off the left most bits that
    ; we are shifting into, but also the left most bit we still want as this
    ; is going to end up in the negative bit marker position (0x80000000).
    ; After the multiplication/shift we Or the result with 0x80000000 to
    ; turn the negative bit on.
    Return BitOR((BitAND($lValue, $m_lOnBits[31 - ($iShiftBits + 1)]) * _
    $m_l2Power[$iShiftBits]) , 0x80000000)

    [/autoit] [autoit][/autoit] [autoit]

    Else

    [/autoit] [autoit][/autoit] [autoit]

    ; (Value And OnBits(31-Shift)) chops off the left most bits that we are
    ; shifting into so we do not get an overflow error when we do the
    ; multiplication/shift
    Return (BitAND($lValue, $m_lOnBits[31 - $iShiftBits]) * _
    $m_l2Power[$iShiftBits])

    Endif
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; RShift (FUNCTION)
    ;
    ; PARAMETERS:
    ; (In) - $lValue - Long- The value to be shifted
    ; (In) - $iShiftBits - Integer - The number of bits to shift the value by
    ;
    ; RETURN VALUE:
    ; Long - The shifted long integer
    ;
    ; DESCRIPTION:
    ; The right shift of an unsigned long integer involves shifting all the set bits
    ; to the right and in-filling on the left with zeros. This function is
    ; equivalent to the >>> operator in Java or the >> operator in C++ when used on
    ; an unsigned long.
    ;*******************************************************************************
    Func RShift($lValue, $iShiftBits)

    [/autoit] [autoit][/autoit] [autoit]

    Local $RShift

    [/autoit] [autoit][/autoit] [autoit]

    ; NOTE: If you can guarantee that the Shift parameter will be in the
    ; range 1 to 30 you can safely strip of this first nested if structure for
    ; speed.
    ;
    ; A shift of zero is no shift at all
    If $iShiftBits = 0 Then
    Return $lValue

    ; A shift of 31 will clear all bits and move the left most bit to the right
    ; most bit position
    ElseIf $iShiftBits = 31 Then
    If BitAND($lValue, 0x80000000) Then
    Return 1
    Else
    Return 0
    Endif

    ; A shift of less than zero or more than 31 is undefined
    ElseIf $iShiftBits < 0 Or $iShiftBits > 31 Then
    SetError(6)
    Endif

    [/autoit] [autoit][/autoit] [autoit]

    ; We do not care about the top most bit or the final bit, the top most bit
    ; will be taken into account in the next stage, the final bit (whether it
    ; is an odd number or not) is being shifted into, so we do not give a jot
    ; about it
    $RShift = int(BitAND($lValue, 0x7FFFFFFE) / $m_l2Power[$iShiftBits])

    [/autoit] [autoit][/autoit] [autoit]

    ; If the top most bit (0x80000000) was set we need to do things differently
    ; as in a normal VB signed long integer the top most bit is used to indicate
    ; the sign of the number, when it is set it is a negative number, so just
    ; deviding by a factor of 2 as above would not work.
    ; NOTE: (lValue And 0x80000000) is equivalent to (lValue < 0], you could
    ; get a very marginal speed improvement by changing the test to (lValue < 0)
    If BitAND($lValue, 0x80000000) Then
    ; We take the value computed so far, and then add the left most negative
    ; bit after it has been shifted to the right the appropriate number of
    ; places
    $RShift = int(BitOR($RShift, (0x40000000 / $m_l2Power[$iShiftBits - 1])))
    Endif

    [/autoit] [autoit][/autoit] [autoit]

    Return $RShift

    [/autoit] [autoit][/autoit] [autoit]

    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; RShiftSigned (FUNCTION)
    ;
    ; PARAMETERS:
    ; (In) - $lValue - Long-
    ; (In) - $iShiftBits - Integer -
    ;
    ; RETURN VALUE:
    ; Long -
    ;
    ; DESCRIPTION:
    ; The right shift of a signed long integer involves shifting all the set bits to
    ; the right and in-filling on the left with the sign bit (0 if positive, 1 if
    ; negative. This function is equivalent to the >> operator in Java or the >>
    ; operator in C++ when used on a signed long integer. Not used in this class,
    ; but included for completeness.
    ;*******************************************************************************
    Func RShiftSigned($lValue , $iShiftBits)

    [/autoit] [autoit][/autoit] [autoit]

    ; NOTE: If you can guarantee that the Shift parameter will be in the
    ; range 1 to 30 you can safely strip of this first nested if structure for
    ; speed.
    ;
    ; A shift of zero is no shift at all
    If $iShiftBits = 0 Then
    Return $lValue

    [/autoit] [autoit][/autoit] [autoit]

    ; A shift of 31 will clear all bits if the left most bit was zero, and will
    ; set all bits if the left most bit was 1 (a negative indicator)
    ElseIf $iShiftBits = 31 Then

    ; NOTE: (lValue And 0x80000000) is equivalent to (lValue < 0), you
    ; could get a very marginal speed improvement by changing the test to
    ; (lValue < 0)
    If BitAND($lValue, 0x80000000) Then
    Return -1
    Else
    Return 0
    Endif

    [/autoit] [autoit][/autoit] [autoit]

    ; A shift of less than zero or more than 31 is undefined
    ElseIf $iShiftBits < 0 Or $iShiftBits > 31 Then
    SetError(6)
    Endif

    [/autoit] [autoit][/autoit] [autoit]

    ; We get the same result by dividing by the appropriate power of 2 and
    ; rounding in the negative direction
    Return Int($lValue / $m_l2Power[$iShiftBits])
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; RotateLeft (FUNCTION)
    ;
    ; PARAMETERS:
    ; (In) - $lValue - Long- Value to act on
    ; (In) - $iShiftBits - Integer - Bits to move by
    ;
    ; RETURN VALUE:
    ; Long - Result
    ;
    ; DESCRIPTION:
    ; Rotates the bits in a long integer to the left, those bits falling off the
    ; left edge are put back on the right edge
    ;*******************************************************************************
    Func RotateLeft($lValue , $iShiftBits)
    Return BitOR(LShift($lValue, $iShiftBits), RShift($lValue, (32 - $iShiftBits)))
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; AddUnsigned (FUNCTION)
    ;
    ; PARAMETERS:
    ; (In) - $lX - Long - First value
    ; (In) - $lY - Long - Second value
    ;
    ; RETURN VALUE:
    ; Long - Result
    ;
    ; DESCRIPTION:
    ; Adds two potentially large unsigned numbers without overflowing
    ;*******************************************************************************
    Func AddUnsigned($lX , $lY )

    $lX8 = BitAND($lX, 0x80000000)
    $lY8 = BitAND($lY, 0x80000000)
    $lX4 = BitAND($lX, 0x40000000)
    $lY4 = BitAND($lY, 0x40000000)

    $lResult = BitAND($lX, 0x3FFFFFFF) + BitAND($lY, 0x3FFFFFFF)

    If BitAND($lX4, $lY4) Then
    $lResult = BitXOR($lResult, 0x80000000, $lX8, $lY8)
    ElseIf BitOR($lX4 , $lY4) Then
    If BitAND($lResult, 0x40000000) Then
    $lResult = BitXOR($lResult, 0xC0000000, $lX8, $lY8)
    Else
    $lResult = BitXOR($lResult, 0x40000000, $lX8, $lY8)
    Endif
    Else
    $lResult = BitXOR($lResult, $lX8, $lY8)
    Endif

    Return $lResult
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; F (FUNCTION)
    ;
    ; DESCRIPTION:
    ; MD5's F function
    ;*******************************************************************************
    Func F($x , $y , $z )
    Return BitOR(BitAND($x, $y) , BitAND((BitNOT($x)), $z))
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; G (FUNCTION)
    ;
    ; DESCRIPTION:
    ; MD5's G function
    ;*******************************************************************************
    Func G($x , $y , $z )
    Return BitOR(BitAND($x, $z) , BitAND($y , (BitNOT($z))))
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; H (FUNCTION)
    ;
    ; DESCRIPTION:
    ; MD5's H function
    ;*******************************************************************************
    Func H($x , $y , $z )
    Return BitXOR($x , $y , $z)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; I (FUNCTION)
    ;
    ; DESCRIPTION:
    ; MD5's I function
    ;*******************************************************************************
    Func I($x , $y , $z )
    Return BitXOR($y , BitOR($x , (BitNOT($z))))
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; FF (Func)
    ;
    ; DESCRIPTION:
    ; MD5's FF procedure
    ;*******************************************************************************
    Func FF(ByRef $a , $b , $c , $d , $x , $s , $ac )
    $a = AddUnsigned($a, AddUnsigned(AddUnsigned(F($b, $c, $d), $x), $ac))
    $a = RotateLeft($a, $s)
    $a = AddUnsigned($a, $b)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; GG (Func)
    ;
    ; DESCRIPTION:
    ; MD5's GG procedure
    ;*******************************************************************************
    Func GG(ByRef $a , $b , $c , $d , $x , $s , $ac )
    $a = AddUnsigned($a, AddUnsigned(AddUnsigned(G($b, $c, $d), $x), $ac))
    $a = RotateLeft($a, $s)
    $a = AddUnsigned($a, $b)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; HH (Func)
    ;
    ; DESCRIPTION:
    ; MD5's HH procedure
    ;*******************************************************************************
    Func HH(ByRef $a , $b , $c , $d , $x , $s , $ac )
    $a = AddUnsigned($a, AddUnsigned(AddUnsigned(H($b, $c, $d), $x), $ac))
    $a = RotateLeft($a, $s)
    $a = AddUnsigned($a, $b)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; II (Func)
    ;
    ; DESCRIPTION:
    ; MD5's II procedure
    ;*******************************************************************************
    Func II(ByRef $a , $b , $c , $d , $x , $s , $ac )
    $a = AddUnsigned($a, AddUnsigned(AddUnsigned(I($b, $c, $d), $x), $ac))
    $a = RotateLeft($a, $s)
    $a = AddUnsigned($a, $b)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; ConvertToWordArray (FUNCTION)
    ;
    ; PARAMETERS:
    ; (In/Out) - $sMessage - String - String message
    ;
    ; RETURN VALUE:
    ; Long() - Converted message as long array
    ;
    ; DESCRIPTION:
    ; Takes the string message and puts it in a long array with padding according to
    ; the MD5 rules.
    ;*******************************************************************************
    Func ConvertToWordArray($sMessage )
    Dim $lWordArray[1]

    [/autoit] [autoit][/autoit] [autoit]

    Const $MODULUS_BITS = 512
    Const $CONGRUENT_BITS = 448

    [/autoit] [autoit][/autoit] [autoit]

    $lMessageLength = StringLen($sMessage)

    [/autoit] [autoit][/autoit] [autoit]

    ; Get padded number of words. Message needs to be congruent to 448 bits,
    ; modulo 512 bits. If it is exactly congruent to 448 bits, modulo 512 bits
    ; it must still have another 512 bits added. 512 bits = 64 bytes
    ; (or 16 * 4 byte words), 448 bits = 56 bytes. This means lMessageSize must
    ; be a multiple of 16 (i.e. 16 * 4 (bytes) * 8 (bits))
    $lNumberOfWords = (int(($lMessageLength + _
    int(($MODULUS_BITS - $CONGRUENT_BITS) / $BITS_TO_A_BYTE)) / _
    int($MODULUS_BITS / $BITS_TO_A_BYTE)) + 1) * _
    int($MODULUS_BITS / $BITS_TO_A_WORD)
    ReDim $lWordArray[$lNumberOfWords]

    [/autoit] [autoit][/autoit] [autoit]

    ; Combine each block of 4 bytes (ascii code of character) into one long
    ; value and store in the message. The high-order (most significant) bit of
    ; each byte is listed first. However, the low-order (least significant) byte
    ; is given first in each word.
    $lBytePosition = 0
    $lByteCount = 0
    Do
    ; Each word is 4 bytes
    $lWordCount = int($lByteCount / $BYTES_TO_A_WORD)

    ; The bytes are put in the word from the right most edge
    $lBytePosition = (Mod($lByteCount , $BYTES_TO_A_WORD)) * $BITS_TO_A_BYTE
    $lWordArray[$lWordCount] = BitOR($lWordArray[$lWordCount] , _
    LShift(Asc(StringMid($sMessage, $lByteCount + 1, 1)), $lBytePosition))
    $lByteCount = $lByteCount + 1
    Until $lByteCount >= $lMessageLength

    [/autoit] [autoit][/autoit] [autoit]

    ; Terminate according to MD5 rules with a 1 bit, zeros and the length in
    ; bits stored in the last two words
    $lWordCount = int($lByteCount / $BYTES_TO_A_WORD)
    $lBytePosition = (Mod($lByteCount , $BYTES_TO_A_WORD)) * $BITS_TO_A_BYTE

    [/autoit] [autoit][/autoit] [autoit]

    ; Add a terminating 1 bit, all the rest of the bits to the end of the
    ; word array will default to zero
    $lWordArray[$lWordCount] = BitOR($lWordArray[$lWordCount] , _
    LShift(0x80, $lBytePosition))

    [/autoit] [autoit][/autoit] [autoit]

    ; We put the length of the message in bits into the last two words, to get
    ; the length in bits we need to multiply by 8 (or left shift 3). This left
    ; shifted value is put in the first word. Any bits shifted off the left edge
    ; need to be put in the second word, we can work out which bits by shifting
    ; right the length by 29 bits.
    $lWordArray[$lNumberOfWords - 2] = LShift($lMessageLength, 3)
    $lWordArray[$lNumberOfWords - 1] = RShift($lMessageLength, 29)

    [/autoit] [autoit][/autoit] [autoit]

    Return $lWordArray
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; WordToHex (FUNCTION)
    ;
    ; PARAMETERS:
    ; (In) - $lValue - Long - Long value to convert
    ;
    ; RETURN VALUE:
    ; String - Hex value to return
    ;
    ; DESCRIPTION:
    ; Takes a long integer and due to the bytes reverse order it extracts the
    ; individual bytes and converts them to hex appending them for an overall hex
    ; value
    ;*******************************************************************************
    Func WordToHex($lValue)

    [/autoit] [autoit][/autoit] [autoit]

    $WordToHex=""

    [/autoit] [autoit][/autoit] [autoit]

    For $lCount = 0 To 3
    $lByte = BitAND(RShift($lValue, $lCount * $BITS_TO_A_BYTE) , _
    $m_lOnBits[$BITS_TO_A_BYTE - 1])
    $WordToHex = $WordToHex & StringRight("0" & Hex($lByte,2), 2)
    Next
    Return $WordToHex
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;*******************************************************************************
    ; MD5 (FUNCTION)
    ;
    ; PARAMETERS:
    ; (In/Out) - sMessage - String - String to be digested
    ;
    ; RETURN VALUE:
    ; String - The MD5 digest
    ;
    ; DESCRIPTION:
    ; This function takes a string message and generates an MD5 digest for it.
    ; sMessage can be up to the VB string length limit of 2^31 (approx. 2 billion)
    ; characters.
    ;
    ; NOTE: Due to the way in which the string is processed the routine assumes a
    ; single byte character set. VB passes unicode (2-byte) character strings, the
    ; ConvertToWordArray function uses on the first byte for each character. This
    ; has been done this way for ease of use, to make the routine truely portable
    ; you could accept a byte array instead, it would then be up to the calling
    ; routine to make sure that the byte array is generated from their string in
    ; a manner consistent with the string type.
    ;*******************************************************************************
    Func MD5($sMessage)

    [/autoit] [autoit][/autoit] [autoit]

    Const $S11 = 7
    Const $S12 = 12
    Const $S13 = 17
    Const $S14 = 22
    Const $S21 = 5
    Const $S22 = 9
    Const $S23 = 14
    Const $S24 = 20
    Const $S31 = 4
    Const $S32 = 11
    Const $S33 = 16
    Const $S34 = 23
    Const $S41 = 6
    Const $S42 = 10
    Const $S43 = 15
    Const $S44 = 21

    [/autoit] [autoit][/autoit] [autoit]

    Class_Initialize()

    [/autoit] [autoit][/autoit] [autoit]

    ; Steps 1 and 2. Append padding bits and length and convert to words
    $x = ConvertToWordArray($sMessage)

    [/autoit] [autoit][/autoit] [autoit]

    ; Step 3. Initialise
    $a = 0x67452301
    $b = 0xEFCDAB89
    $c = 0x98BADCFE
    $d = 0x10325476

    [/autoit] [autoit][/autoit] [autoit]

    ; Step 4. Process the message in 16-word blocks
    For $k = 0 To UBound($x)-1 Step 16
    $AA = $a
    $BB = $b
    $CC = $c
    $DD = $d

    [/autoit] [autoit][/autoit] [autoit]

    ; The hex number on the end of each of the following procedure calls is
    ; an element from the 64 element table constructed with
    ; T(i) = Int(4294967296 * Abs(Sin(i))) where i is 1 to 64.
    ;
    ; However, for speed we don't want to calculate the value every time.
    FF( $a, $b, $c, $d, $x[$k + 0], $S11, 0xD76AA478 )
    FF( $d, $a, $b, $c, $x[$k + 1], $S12, 0xE8C7B756 )
    FF( $c, $d, $a, $b, $x[$k + 2], $S13, 0x242070DB )
    FF( $b, $c, $d, $a, $x[$k + 3], $S14, 0xC1BDCEEE )
    FF( $a, $b, $c, $d, $x[$k + 4], $S11, 0xF57C0FAF )
    FF( $d, $a, $b, $c, $x[$k + 5], $S12, 0x4787C62A )
    FF( $c, $d, $a, $b, $x[$k + 6], $S13, 0xA8304613 )
    FF( $b, $c, $d, $a, $x[$k + 7], $S14, 0xFD469501 )
    FF( $a, $b, $c, $d, $x[$k + 8], $S11, 0x698098D8 )
    FF( $d, $a, $b, $c, $x[$k + 9], $S12, 0x8B44F7AF )
    FF( $c, $d, $a, $b, $x[$k + 10], $S13, 0xFFFF5BB1)
    FF( $b, $c, $d, $a, $x[$k + 11], $S14, 0x895CD7BE)
    FF( $a, $b, $c, $d, $x[$k + 12], $S11, 0x6B901122)
    FF( $d, $a, $b, $c, $x[$k + 13], $S12, 0xFD987193)
    FF( $c, $d, $a, $b, $x[$k + 14], $S13, 0xA679438E)
    FF( $b, $c, $d, $a, $x[$k + 15], $S14, 0x49B40821)

    [/autoit] [autoit][/autoit] [autoit]

    GG( $a, $b, $c, $d, $x[$k + 1], $S21, 0xF61E2562 )
    GG( $d, $a, $b, $c, $x[$k + 6], $S22, 0xC040B340 )
    GG( $c, $d, $a, $b, $x[$k + 11], $S23, 0x265E5A51)
    GG( $b, $c, $d, $a, $x[$k + 0], $S24, 0xE9B6C7AA )
    GG( $a, $b, $c, $d, $x[$k + 5], $S21, 0xD62F105D )
    GG( $d, $a, $b, $c, $x[$k + 10], $S22, 0x2441453 )
    GG( $c, $d, $a, $b, $x[$k + 15], $S23, 0xD8A1E681)
    GG( $b, $c, $d, $a, $x[$k + 4], $S24, 0xE7D3FBC8 )
    GG( $a, $b, $c, $d, $x[$k + 9], $S21, 0x21E1CDE6 )
    GG( $d, $a, $b, $c, $x[$k + 14], $S22, 0xC33707D6)
    GG( $c, $d, $a, $b, $x[$k + 3], $S23, 0xF4D50D87 )
    GG( $b, $c, $d, $a, $x[$k + 8], $S24, 0x455A14ED )
    GG( $a, $b, $c, $d, $x[$k + 13], $S21, 0xA9E3E905)
    GG( $d, $a, $b, $c, $x[$k + 2], $S22, 0xFCEFA3F8 )
    GG( $c, $d, $a, $b, $x[$k + 7], $S23, 0x676F02D9 )
    GG( $b, $c, $d, $a, $x[$k + 12], $S24, 0x8D2A4C8A)

    HH( $a, $b, $c, $d, $x[$k + 5], $S31, 0xFFFA3942 )
    HH( $d, $a, $b, $c, $x[$k + 8], $S32, 0x8771F681 )
    HH( $c, $d, $a, $b, $x[$k + 11], $S33, 0x6D9D6122)
    HH( $b, $c, $d, $a, $x[$k + 14], $S34, 0xFDE5380C)
    HH( $a, $b, $c, $d, $x[$k + 1], $S31, 0xA4BEEA44 )
    HH( $d, $a, $b, $c, $x[$k + 4], $S32, 0x4BDECFA9 )
    HH( $c, $d, $a, $b, $x[$k + 7], $S33, 0xF6BB4B60 )
    HH( $b, $c, $d, $a, $x[$k + 10], $S34, 0xBEBFBC70)
    HH( $a, $b, $c, $d, $x[$k + 13], $S31, 0x289B7EC6)
    HH( $d, $a, $b, $c, $x[$k + 0], $S32, 0xEAA127FA )
    HH( $c, $d, $a, $b, $x[$k + 3], $S33, 0xD4EF3085 )
    HH( $b, $c, $d, $a, $x[$k + 6], $S34, 0x4881D05 )
    HH( $a, $b, $c, $d, $x[$k + 9], $S31, 0xD9D4D039 )
    HH( $d, $a, $b, $c, $x[$k + 12], $S32, 0xE6DB99E5)
    HH( $c, $d, $a, $b, $x[$k + 15], $S33, 0x1FA27CF8)
    HH( $b, $c, $d, $a, $x[$k + 2], $S34, 0xC4AC5665 )

    [/autoit] [autoit][/autoit] [autoit]

    II( $a, $b, $c, $d, $x[$k + 0], $S41, 0xF4292244 )
    II( $d, $a, $b, $c, $x[$k + 7], $S42, 0x432AFF97 )
    II( $c, $d, $a, $b, $x[$k + 14], $S43, 0xAB9423A7)
    II( $b, $c, $d, $a, $x[$k + 5], $S44, 0xFC93A039 )
    II( $a, $b, $c, $d, $x[$k + 12], $S41, 0x655B59C3)
    II( $d, $a, $b, $c, $x[$k + 3], $S42, 0x8F0CCC92 )
    II( $c, $d, $a, $b, $x[$k + 10], $S43, 0xFFEFF47D)
    II( $b, $c, $d, $a, $x[$k + 1], $S44, 0x85845DD1 )
    II( $a, $b, $c, $d, $x[$k + 8], $S41, 0x6FA87E4F )
    II( $d, $a, $b, $c, $x[$k + 15], $S42, 0xFE2CE6E0)
    II( $c, $d, $a, $b, $x[$k + 6], $S43, 0xA3014314 )
    II( $b, $c, $d, $a, $x[$k + 13], $S44, 0x4E0811A1)
    II( $a, $b, $c, $d, $x[$k + 4], $S41, 0xF7537E82 )
    II( $d, $a, $b, $c, $x[$k + 11], $S42, 0xBD3AF235)
    II( $c, $d, $a, $b, $x[$k + 2], $S43, 0x2AD7D2BB )
    II( $b, $c, $d, $a, $x[$k + 9], $S44, 0xEB86D391 )

    [/autoit] [autoit][/autoit] [autoit]

    $a = AddUnsigned($a, $AA)
    $b = AddUnsigned($b, $BB)
    $c = AddUnsigned($c, $CC)
    $d = AddUnsigned($d, $DD)
    Next

    [/autoit] [autoit][/autoit] [autoit]

    ; Step 5. Output the 128 bit digest
    Return StringLower(WordToHex($a) & WordToHex($b) & WordToHex($c) & WordToHex($d))
    EndFunc

    [/autoit]