2017-01-26 13 views
0

PHPでMD5ハッシングアルゴリズムを実装しようとしていて、以下のコードを作成しました。しかし、テスト入力 "test"で関数を実行すると、 "098f6bcd4621d373cade4e832627b4f6"の代わりに "21aa63b9882532cd590623dbd8f2fa225350d682"という文字列が生成されます。PHP MD5実装で正しい結果が生成されない

なぜ私はこれがエラーを返すのかというアイディアを完全に使い果たしました。誰かが私を助けてくれたら非常に感謝しています。

編集:私はプロダクションではなく、学校のプロジェクトでこれを使用しています。

マイコード:

<?php 

/** 
* Created by PhpStorm. 
* User: Sam Gunner 
* Date: 25/01/2017 
* Time: 18:37 
*/ 
class md5 
{ 
    private $k; 
    private $s; 

    //Constants as defined by the specification 
    private $a0 = 0x67452301; 
    private $b0 = 0xefcdab89; 
    private $c0 = 0x98badcfe; 
    private $d0 = 0x10325476; 

    //Convert a character to its binary representation using ASCII 
    private function convertCharToByteString($char) { 
     $charNum = ord($char); 
     $charNumString = decbin($charNum); 
     $charNumString = str_pad($charNumString, 8, '0', STR_PAD_LEFT); 
     return $charNumString; 
    } 

    //Takes in a number of zeroes and the string, and then adds that number of zeroes to the end of the string 
    private function padZeroRight($str, $amount) { 
     for ($i = 0; $i < $amount; $i++) { 
      $str .= '0'; 
     } 

     return $str; 
    } 

    //Splits up a string into several pieces 
    private function getCharChunks($original, $length) { 
     $chunks = Array(); 
     $currentChunk = null; 
     $currentStart = null; 
     $numberOfParts = ceil(strlen($original)/$length); //Get the number of chunks 

     for ($i = 0; $i < $numberOfParts; $i++) { 
      $currentStart = ($i * $length) - ($length - 1); //Get the starting position of the substring 
      $currentChunk = substr($original, $currentStart, $length); 
      $chunks[$i] = $currentChunk; 
     } 

     return $chunks; 
    } 

    //Easy way of converting multiple binary integers to array of decimal integers 
    private function convertChunkArrayToIntegers($chunkArray) { 
     $finalChunks = Array(); 
     for ($i = 0; $i < count($chunkArray); $i++) { 
      $finalChunks[$i] = decbin($chunkArray[$i]); 
     } 

     return $finalChunks; 
    } 

    //Begin MD5-specific functions 
    private function F($B, $C, $D) { 
     return ($B & $C) | ((~$B) & $D); 
    } 

    private function G($B, $C, $D) { 
     return ($B & $D) | ($C & (~$D)); 
    } 

    private function H($B, $C, $D) { 
     return ($B^$C^$D); 
    } 

    private function I($B, $C, $D) { 
     return ($C^($B | (~$D))); 
    } 

    private function rotate($decimal, $bits) { //returns hex 
     return (($decimal << $bits) | ($decimal >> (32 - $bits))) & 0xffffffff; 
    } 

    public function __construct() { 
     $this->s = Array(
      7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 
      5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 
      4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 
      6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 
     ); 

     for ($i = 0; $i < 64; $i++) { //Generate the constants that are defined in the specification 
      $this->k[$i] = floor(abs(sin($i + 1)) * pow(2, 32)); 
     } 
    } 

    //Returns the MD5 hash of a message in string form 
    public function hash($message) { 
     $finalStr = ''; 
     $subChunks = null; 
     $A = null; 
     $B = null; 
     $C = null; 
     $D = null; 
     $F = null; 
     $g = null; 
     $DTemp = null; 

     for ($i = 0; $i < strlen($message); $i++) { //Change the string representation of the message into a series of bits, which we can manipulate 
      $finalStr .= $this->convertCharToByteString(substr($finalStr, $i, 1)); 
     } 

     $finalStr .= '1'; //Append 1, as the specification says to 

     $messageLen = strlen($finalStr); 
     $messageLenFinal = $messageLen % 512; //Find out how much we are under a multiple of 512 

     if ($messageLenFinal > 448) { //If the message length remainder is longer than 448, then we need to add some more zeroes to get it to 448 over 
      $remainingToAdd = (512 - $messageLenFinal) + 448; //'tip it over the edge' and then add 448 to make it 64 below 512 
     } else { 
      $remainingToAdd = 448 - $messageLenFinal; 
     } 

     $finalStr = $this->padZeroRight($finalStr, $remainingToAdd); //Add zeroes onto the end until criteria is met 
     //$messageLen = $messageLen % (pow(2, 64)); //Get the length of the message MOD 2 pow 64 
     $messageLen = strlen($finalStr); 

     $messageLenStr = decbin($messageLen); //Convert the decimal representation to binary 
     $messageLenStr = str_pad($messageLenStr, 64, "0", STR_PAD_LEFT); //Pad the message with zeroes to make it 64 bits long 

     $finalStr .= $messageLenStr; 

     $chunks = $this->getCharChunks($finalStr, 512); //Get message in 512-bit chunks 

     foreach ($chunks as $chunk) { 
      $subChunks = $this->convertChunkArrayToIntegers($this->getCharChunks($chunk, 32)); //Get sub chunks of 32-bit size 
      $A = $this->a0; 
      $B = $this->b0; 
      $C = $this->c0; 
      $D = $this->d0; 

      for ($i = 0; $i < 64; $i++) { 
       if ($i >= 0 && $i < 16) { 
        $F = $this->F($B, $C, $D); 
        $g = $i; 
       } elseif ($i > 15 && $i <32) { 
        $F = $this->G($B, $C, $D); 
        $g = ((5 * $i) + 1) % 16; 
       } elseif ($i > 31 && $i < 48) { 
        $F = $this->H($B, $C, $D); 
        $g = ((3 * $i) + 5) % 16; 
       } elseif ($i > 47 && $i < 64) { 
        $F = $this->I($B, $C, $D); 
        $g = (7 * $i) % 16; 
       } 

       $DTemp = $D; 
       $D = $C; 
       $C = $B; 
       $B = $B + $this->rotate(($A + $F + $this->k[$i] + $subChunks[$g]), $this->s[$i]); 
       $A = $DTemp; 
      } 

      $this->a0 += $A; 
      $this->b0 += $B; 
      $this->c0 += $C; 
      $this->d0 += $D; 
     } 

     $final = dechex($this->a0) . dechex($this->b0) . dechex($this->c0) . dechex($this->d0); 
     return $final; 
    } 
} 

多くのおかげで、

- サム

+0

なぜMD5をパスワードに使用したいですか?ライブ制作には使用しないでください。この日と年齢ではありません。 –

+0

ああ、プロダクションで実際に使っているのではなく、私が学校のプロジェクトでこれをやっていると言っていたはずです。私はアルゴリズムの欠陥を知っています –

答えて

0

あなたはラウンドの終了時に実行している4回の加算:

$this->a0 += $A; 
$this->b0 += $B; 
$this->c0 += $C; 
$this->d0 += $D; 

はありませんラッピング。これは、A/B/C/Dが大きすぎる原因となっています。これはおそらく128の代わりに160ビットの長さになるでしょう。dechex()の結果を埋め込む必要があります4つのコンポーネントのうちの1つが非常に小さくなった場合、結果が短すぎることを避けるための最終段階です。

(同様に他の問題があるかもしれません - 。これらは私が気づいただけで最初のものです)


それがすべてのオプションなら、私はが強くはあなたがCを使用することをお勧めしますこのプロジェクトPHPは、低レベルの暗号コードの作成にはあまり適していません。このような問題で頻繁に取り組んでいます。

関連する問題