Ankündigung

Einklappen
Keine Ankündigung bisher.

Eigener MD5 Algorithmus funktioniert nicht

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Eigener MD5 Algorithmus funktioniert nicht

    Zur Übung und zum Verständnis über die Programmierung mit Bits und Bytes (bitweise Operationen, Bitverschiebung, Bitwertigkeit, Bytereihenfolge, etc) möchte ich mir meine eigene Implementierung eines MD5-Algorithmus zusammenbauen. Leider kommt am Ende nicht das selbe Ergebnis wie bei der Originalfunktion raus.
    Ich habe mich der Erklärung des RFC 1321 bedient.

    Ich bin mir auch bewusst, dass es im Internet schon teilweise richtige Implementierungen gibt. Doch ich würde gern wissen, wo bei meinem Code der Fehler liegt, da ich afaik alles berücksichtigt habe was im RFC steht

    PHP-Code:
    <?php //https://tools.ietf.org/html/rfc1321
        
    $little_endian true//Bytereihenfolge
        
        
    $a0 hexdec("67452301"); //Buffer variables (big endian)
        
    $b0 hexdec("efcdab89");
        
    $c0 hexdec("98badcfe");
        
    $d0 hexdec("10325476");
        
    /*$a0 = hexdec("01234567"); //Buffer variables (little endian)
        $b0 = hexdec("89abcdef");
        $c0 = hexdec("fedcba98");
        $d0 = hexdec("76543210");*/
        
    function F($x$y$z){return (($x $y) | ((~$x) & $z));} //Compression functions
        
    function G($x$y$z){return (($x $z) | ($y & (~$z)));}
        function 
    H($x$y$z){return ($x $y $z);}
        function 
    I($x$y$z){return ($y ^ ($x | (~$z)));}
        
        
    $T = array();
        for(
    $i 1$i <= 64$i++){
            
    $T[$i] = floor(abs(sin($i)) * 4294967296);
        }
        

        
    $in "Hallo, Welt!";
        
    //echo "Input: <strong>".$in."</strong><br>";
        
        
    $b ""//Binary string of input
        
    for($i 0$i strlen($in); $i++){
            
    $byte decbin(ord(substr($in$i1)));
            while(
    strlen($byte) < 8){ //pad 0's before the byte string while it's length isn't 8
                
    $byte "0".$byte;
            }
            
    $b .= $byte;
        }
        
    $b_original $b//original binary string
        
        /*
          MD5
        */
        
        //1.1 append "1"
        
    $b .= "1";
        
        
    //1.2 pad with "0" until length is 64 bit smaller than a multiple of 512
        
    while(strlen($b) % 512 != 448){
            
    $b .= "0";
        }
        
        
    //2.1 Append the bit length of input stream in 64 bits
        
    $len_bin decbin(strlen($b_original));
        if(
    strlen($len_bin) < 64){
            while(
    strlen($len_bin) < 64){
                
    $len_bin "0" $len_bin;
            }
        }else if(
    strlen($len_bin) > 64){
            while(
    strlen($len_bin) > 64){
                
    $len_bin substr($len_bin1);
            }
        }
        
    $b_len_low_order_word substr($len_bin32);
        
    $b_len_high_order_word substr($len_bin032);
        
    $b .= $little_endian ?
            
    implode(""array_reverse(splitIntoBytes($b_len_low_order_word))).implode(""array_reverse(splitIntoBytes($b_len_high_order_word))) :
            
    $b_len_low_order_word.$b_len_high_order_word;
        
        
    //echo $b . "<br>";
        
        
    $N strlen($b) / 32//Number of 32-bit-words, a multiple of 16
        
        //4.3 divide input stream into 512 bit blocks
        
    for($i 0$i < ($N/16); $i++){
            
            
    $block substr($b$i 512512); //current 512 bit block
            
            
    $M = array();
            for(
    $j 0$j 16$j++){ //divide block into 32 bit words
                
    $word substr($block$j 3232); //current 32 bit word
                
    $M[$j] = $little_endian bindec(implode(""array_reverse(splitIntoBytes($word)))) : bindec($word);
                
    //echo $word . "<br>";
            
    }
            
            
    $AA $a0;
            
    $BB $b0;
            
    $CC $c0;
            
    $DD $d0;
            
            echo 
    "Block " $i+", before Round 1:<br>A: ".dechex($a0)."<br>B: ".dechex($b0)."<br>C: ".dechex($c0)."<br>D: ".dechex($d0)."<br><br>";
            
            
    //Round 1 (all values are decimal)
            
    R1($a0$b0$c0$d0071);
            
    R1($d0$a0$b0$c01122);
            
    R1($c0$d0$a0$b02173);
            
    R1($b0$c0$d0$a03224);
            
            
    R1($a0$b0$c0$d0475);
            
    R1($d0$a0$b0$c05126);
            
    R1($c0$d0$a0$b06177);
            
    R1($b0$c0$d0$a07228);
            
            
    R1($a0$b0$c0$d0879);
            
    R1($d0$a0$b0$c091210);
            
    R1($c0$d0$a0$b0101711);
            
    R1($b0$c0$d0$a0112212);
            
            
    R1($a0$b0$c0$d012713);
            
    R1($d0$a0$b0$c0131214);
            
    R1($c0$d0$a0$b0141715);
            
    R1($b0$c0$d0$a0152216);
            
            echo 
    "Block " $i+", before Round 2:<br>A: ".dechex($a0)."<br>B: ".dechex($b0)."<br>C: ".dechex($c0)."<br>D: ".dechex($d0)."<br><br>";
            
            
    //Round 2
            
    R2($a0$b0$c0$d01517);
            
    R2($d0$a0$b0$c06918);
            
    R2($c0$d0$a0$b0111419);
            
    R2($b0$c0$d0$a002020);
            
            
    R2($a0$b0$c0$d05521);
            
    R2($d0$a0$b0$c010922);
            
    R2($c0$d0$a0$b0151423);
            
    R2($b0$c0$d0$a042024);
            
            
    R2($a0$b0$c0$d09525);
            
    R2($d0$a0$b0$c014926);
            
    R2($c0$d0$a0$b031427);
            
    R2($b0$c0$d0$a082028);
            
            
    R2($a0$b0$c0$d013529);
            
    R2($d0$a0$b0$c02930);
            
    R2($c0$d0$a0$b071431);
            
    R2($b0$c0$d0$a0122032);
            
            echo 
    "Block " $i+", before Round 3:<br>A: ".dechex($a0)."<br>B: ".dechex($b0)."<br>C: ".dechex($c0)."<br>D: ".dechex($d0)."<br><br>";
            
            
    //Round 3
            
    R3($a0$b0$c0$d05433);
            
    R3($d0$a0$b0$c081134);
            
    R3($c0$d0$a0$b0111635);
            
    R3($b0$c0$d0$a0142336);
            
            
    R3($a0$b0$c0$d01437);
            
    R3($d0$a0$b0$c041138);
            
    R3($c0$d0$a0$b071639);
            
    R3($b0$c0$d0$a0102340);
            
            
    R3($a0$b0$c0$d013441);
            
    R3($d0$a0$b0$c001142);
            
    R3($c0$d0$a0$b031643);
            
    R3($b0$c0$d0$a062344);
            
            
    R3($a0$b0$c0$d09445);
            
    R3($d0$a0$b0$c0121146);
            
    R3($c0$d0$a0$b0151647);
            
    R3($b0$c0$d0$a022348);
            
            echo 
    "Block " $i+", before Round 4:<br>A: ".dechex($a0)."<br>B: ".dechex($b0)."<br>C: ".dechex($c0)."<br>D: ".dechex($d0)."<br><br>";
            
            
    //Round 4
            
    R4($a0$b0$c0$d00649);
            
    R4($d0$a0$b0$c071050);
            
    R4($c0$d0$a0$b0141551);
            
    R4($b0$c0$d0$a052152);
            
            
    R4($a0$b0$c0$d012653);
            
    R4($d0$a0$b0$c031054);
            
    R4($c0$d0$a0$b0101555);
            
    R4($b0$c0$d0$a012156);
            
            
    R4($a0$b0$c0$d08657);
            
    R4($d0$a0$b0$c0151058);
            
    R4($c0$d0$a0$b061559);
            
    R4($b0$c0$d0$a0132160);
            
            
    R4($a0$b0$c0$d04661);
            
    R4($d0$a0$b0$c0111062);
            
    R4($c0$d0$a0$b021563);
            
    R4($b0$c0$d0$a092164);
            
            
    $a0 $a0 $AA;
            
    $b0 $b0 $BB;
            
    $c0 $c0 $CC;
            
    $d0 $d0 $DD;
        }
        
        
    //decimal variables to binary
        
    $a0 appendZeroAtBegin(decbin($a0), 32);
        
    $b0 appendZeroAtBegin(decbin($b0), 32);
        
    $c0 appendZeroAtBegin(decbin($c0), 32);
        
    $d0 appendZeroAtBegin(decbin($d0), 32);
        
        echo 
    "End:<br>A: ".binhex($a0)."<br>";
        echo 
    "B: ".binhex($b0)."<br>";
        echo 
    "C: ".binhex($c0)."<br>";
        echo 
    "D: ".binhex($d0)."<br>";
        
        
    /*$a_b = array_reverse(splitIntoBytes($a));
        $b_b = array_reverse(splitIntoBytes($b));
        $c_b = array_reverse(splitIntoBytes($c));
        $d_b = array_reverse(splitIntoBytes($d));*/
        
        //$hash = implode("", $a_b).implode("", $b_b).implode("", $c_b).implode("", $d_b);
        
    $hash $a0.$b0.$c0.$d0;
        
        
    //echo "Hash value: <strong>" . binhex($hash) . "</strong><br>Original MD5: <strong>" . md5($in) . "</strong><br>";
        
    echo binhex($hash) . "<br>" md5($in);

    function 
    hexbin($str){
            
    $hexbinmap = array(
                
    "0" => "0000",
                
    "1" => "0001",
                
    "2" => "0010",
                
    "3" => "0011",
                
    "4" => "0100",
                
    "5" => "0101",
                
    "6" => "0110",
                
    "7" => "0111",
                
    "8" => "1000",
                
    "9" => "1001",
                
    "a" => "1010",
                
    "b" => "1011",
                
    "c" => "1100",
                
    "d" => "1101",
                
    "e" => "1110",
                
    "f" => "1111");
            
    $bin "";
            for (
    $i 0$i strlen($str); $i++)
            {
                
    $bin .= $hexbinmap[strtolower($str[$i])];
            }
            return 
    $bin;
        }
        function 
    binhex($str){
            
    $binhexmap = array(
                
    "0000" => "0",
                
    "0001" => "1",
                
    "0010" => "2",
                
    "0011" => "3",
                
    "0100" => "4",
                
    "0101" => "5",
                
    "0110" => "6",
                
    "0111" => "7",
                
    "1000" => "8",
                
    "1001" => "9",
                
    "1010" => "a",
                
    "1011" => "b",
                
    "1100" => "c",
                
    "1101" => "d",
                
    "1110" => "e",
                
    "1111" => "f");
            
    $hex "";
            foreach(
    explode("\r\n"chunk_split($str4)) as $ch){
                if(empty(
    $ch)) continue;
                
    $hex .= $binhexmap[$ch];
            }
            return 
    $hex;
        }
        
        function 
    rotateLeft($exp$s$binary false){
            
    $new_exp $binary $exp decbin($exp);
            
            
    //append first bit behind the last s times
            
    for($i 0$i $s$i++){
                
    $new_exp substr($new_exp1) . substr($new_exp01);
            }
            
            return 
    $binary $new_exp bindec($new_exp);
        }
        
        function 
    appendZeroAtBegin($bin$len){
            
    $new_bin $bin;
            while(
    strlen($new_bin) < $len){
                
    $new_bin "0" $new_bin;
            }
            return 
    $new_bin;
        }
        
        function 
    splitIntoBytes($bin){
            
    //returns high order bits first
            
    $arr = array();
            if(
    strlen($bin) % != 0) return null;
            for(
    $i 0$i strlen($bin) / 8$i++){
                
    $arr[] = substr($bin$i 88);
            }
            return 
    $arr;
        }
        
        function 
    R1(&$a$b$c$d$k$s$i){
            global 
    $M$T;
             
    $a rotateLeft(($a F($b$c$d) + $M[$k] + $T[$i]), $s) + $b;
            
    /*$a = F($b, $c, $d) + $M[$k] + $T[$i];
            $a = rotateLeft($a, $s);
            $a += $b;*/
        
    }
        function 
    R2(&$a$b$c$d$k$s$i){
            global 
    $M$T;
             
    $a rotateLeft(($a G($b$c$d) + $M[$k] + $T[$i]), $s) + $b;
            
    /*$a = G($b, $c, $d) + $M[$k] + $T[$i];
            $a = rotateLeft($a, $s);
            $a += $b;*/
        
    }
        function 
    R3(&$a$b$c$d$k$s$i){
            global 
    $M$T;
             
    $a rotateLeft(($a H($b$c$d) + $M[$k] + $T[$i]), $s) + $b;
            
    /*$a = H($b, $c, $d) + $M[$k] + $T[$i];
            $a = rotateLeft($a, $s);
            $a += $b;*/
        
    }
        function 
    R4(&$a$b$c$d$k$s$i){
            global 
    $M$T;
             
    $a rotateLeft(($a I($b$c$d) + $M[$k] + $T[$i]), $s) + $b;
            
    /*$a = I($b, $c, $d) + $M[$k] + $T[$i];
            $a = rotateLeft($a, $s);
            $a += $b;*/
        
    }
    Vielen Dank im Voraus
    LG

  • #2
    Warum programmierst du bin2hex() und hex2bin() nach? Warum ständig die Herumwandelei zwischen Strings und Zahlen? Irgendwie machst du da sehr viel unnötig.

    Kommentar


    • #3
      Zitat von hellbringer Beitrag anzeigen
      Warum programmierst du bin2hex() und hex2bin() nach? Warum ständig die Herumwandelei zwischen Strings und Zahlen? Irgendwie machst du da sehr viel unnötig.
      Das mit den Konvertierungsfunktionen habe ich erst bemerkt als ich die schon drin hatte...

      Die Herumwandelei war meines achtens eher weniger als bei den anderen Implementationen die ich gesehen habe. Ich benutze für die Berechnungen Dezimal, für die Ausgabe Hexadezimal und für Bitoperationen Strings.

      Kommentar


      • #4
        PHP kann Bit-Operationen. Wozu die Umwandelei in Strings?

        Statt hexdec("67452301") wäre es zB. sinnvoller gleich 0x67452301 zu schreiben.

        Hier mal zur Anregung ein kleiner Auszug aus meiner selbstgebastelten MD5-Funktion:
        PHP-Code:
            // 3.1 Step 1. Append Padding Bits

            
        $messageBitLength strlen($message) * 8;
            
        $message .= "\x80";

            
        $padding 56 - (strlen($message) % 64);
            if (
        $padding 0) {
                
        $padding += 64;
            }
            
        $message .= str_repeat("\x00"$padding);

            
        // 3.2 Step 2. Append Length

            
        $message .= pack('P'$messageBitLength);

            
        // 3.3 Step 3. Initialize MD Buffer

            
        $mdBuffer = [
                
        0x67452301,
                (int)
        0xEFCDAB89,
                (int)
        0x98BADCFE,
                
        0x10325476
            
        ]; 

        Kommentar


        • #5
          Zitat von hellbringer Beitrag anzeigen
          PHP kann Bit-Operationen. Wozu die Umwandelei in Strings?

          Statt hexdec("67452301") wäre es zB. sinnvoller gleich 0x67452301 zu schreiben.
          Ich meinte mit Bitoperationen das Padding-Zeug.
          Mit dem Argument, dass man 0x... schreiben kann gehe ich mit.

          Kannst du mal von einem Beispielstring die gepaddete Binärzeichenfolge nach deinem 3.2. Punkt zeigen?

          Kommentar


          • #6
            Zitat von Spamversender Beitrag anzeigen
            Kannst du mal von einem Beispielstring die gepaddete Binärzeichenfolge nach deinem 3.2. Punkt zeigen?
            Warum probierst du es nicht selber aus?

            Kommentar


            • #7
              Zitat von hellbringer Beitrag anzeigen

              Warum probierst du es nicht selber aus?
              Wenn ich deinen Code ausführe, kommt keine 512-Bit-Zeichenfolge raus. Und die Methode pack("P", ...) funktioniert bei mir nicht (mit v oder L übrigens auch nicht).

              Kommentar


              • #8
                Zitat von Spamversender Beitrag anzeigen
                Wenn ich deinen Code ausführe, kommt keine 512-Bit-Zeichenfolge raus. Und die Methode pack("P", ...) funktioniert bei mir nicht (mit v oder L übrigens auch nicht).
                PHP-Code:
                $message "foobar";

                // 3.1 Step 1. Append Padding Bits

                $messageBitLength strlen($message) * 8;
                $message .= "\x80";

                $padding 56 - (strlen($message) % 64);
                if (
                $padding 0) {
                    
                $padding += 64;
                }
                $message .= str_repeat("\x00"$padding);

                // 3.2 Step 2. Append Length

                $message .= pack('P'$messageBitLength);

                echo 
                strlen($message) * PHP_EOL;
                // 512

                echo bin2hex($message) . PHP_EOL;
                // 666f6f62617280000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000 

                Kommentar


                • #9
                  Zitat von Spamversender Beitrag anzeigen
                  Die Herumwandelei war meines achtens eher weniger als bei den anderen Implementationen die ich gesehen habe. Ich benutze für die Berechnungen Dezimal, für die Ausgabe Hexadezimal und für Bitoperationen Strings.
                  Du hast hier ein massives Verständnisproblem von PC und dem Umgang mit Zahlen. Ein Computer kennt weder Dezimal, Oktal, Hexadezimal, sondern NUR Binär. Er kann nicht in Dezimal rechnen!
                  Windows Server gehören NICHT ins Internet!

                  Dildo? Dildo!

                  Kommentar


                  • #10
                    Zitat von trollface Beitrag anzeigen
                    Du hast hier ein massives Verständnisproblem von PC und dem Umgang mit Zahlen. Ein Computer kennt weder Dezimal, Oktal, Hexadezimal, sondern NUR Binär. Er kann nicht in Dezimal rechnen!
                    Ich hab das nur gemacht, um mich auch noch darin zurechtzufinden.
                    Habe jetzt die Variante von hellbringer probiert, kommt aber letztendlich auf das gleiche (immer noch falsche) Ergebnis raus. Ich glaube der Fehler liegt im Rotieren, ich sehe ihn aber nicht...

                    Kommentar


                    • #11
                      Das Problem ist, dass du etwas in PHP machen willst, wofür PHP überhaupt nicht geeignet ist. Dazu muss man einige Workarounds bauen. Nicht gerade ein Anfängerthema bzw. Übungsprojekt. Hinzu kommt, dass sich ein 32-Bit PHP ganz anders als ein 64-Bit PHP verhält. Also je nachdem, für welches PHP du entwickelst, müssen andere Workarounds geschrieben werden.

                      Kommentar


                      • #12
                        Ich habe es jetzt doch hinbekommen. Der Fehler lag in der rotateLeft-Methode, da wurde nicht geprüft ob der Eingabestring 32 Bit groß ist. Und noch ein bisschen mit Bytereihenfolgen rumgespielt und ab und zu die Zahlen auf 32 Bit gekürzt

                        Kommentar

                        Lädt...
                        X