PHP MD5实现不会产生正确的结果

PHP MD5实现不会产生正确的结果,php,oop,hash,passwords,md5,Php,Oop,Hash,Passwords,Md5,我一直在尝试在PHP中实现MD5哈希算法,并生成了下面的代码。但是,当我使用测试输入“test”运行函数时,它会生成字符串“21aa63b9882532cd590623dbd8f2fa225350d682”,而不是预期的“098F6BC4621D3CADE4E832627B4F6” 我完全不知道为什么这会返回一个错误,如果有人能帮助我,我将不胜感激 编辑:我不是在制作中使用这个,而是在学校的项目中使用 我的代码: <?php /** * Created by PhpStorm. *

我一直在尝试在PHP中实现MD5哈希算法,并生成了下面的代码。但是,当我使用测试输入“test”运行函数时,它会生成字符串“21aa63b9882532cd590623dbd8f2fa225350d682”,而不是预期的“098F6BC4621D3CADE4E832627B4F6”

我完全不知道为什么这会返回一个错误,如果有人能帮助我,我将不胜感激

编辑:我不是在制作中使用这个,而是在学校的项目中使用

我的代码:

<?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;
    }
}

您在一轮结束时执行的四项添加操作:

$this->a0 += $A;
$this->b0 += $B;
$this->c0 += $C;
$this->d0 += $D;
你没有包装。这会导致A/B/C/D变得太大——这可能就是为什么您的输出的长度是160位而不是128位

请注意,您还需要在最后阶段填充
dechex()
的结果,以避免在四个组件中的一个非常小时给出过短的结果

(可能还有其他问题——这些只是我注意到的第一个问题。)



如果这是一个选项,我强烈建议您在这个项目中使用C。PHP不太适合编写低级加密代码;您会发现自己经常遇到类似的问题。

为什么要使用MD5作为密码?这不应该用于现场生产;不是在这个时代。啊,我应该说我做这个是为了一个学校的项目,而不是在实际生产中使用它。我知道这个算法有缺陷