Я пытаюсь реализовать алгоритм хэширования MD5 в PHP, и я подготовил код ниже. Однако, когда я запускаю функцию с тестовым вводом «test», она выдает строку «21aa63b9882532cd590623dbd8f2fa225350d682» в отличие от ожидаемого «098f6bcd4621d373cade4e832627b4f6».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;
}
}
Большое спасибо,
- Сэм
Почему вы хотите использовать MD5 для паролей? это не должно использоваться для живого производства; не в этот день и в возрасте. –
Ах, я должен был сказать, что я делаю это для школьного проекта, а не фактически использую его в производстве. Я знаю об ошибках с алгоритмом –