Можете ли вы преобразовать вывод php crypt () в действительный MD5?
-
19-08-2019 - |
Вопрос
У меня есть несколько строк, которые были зашифрованы с помощью функции PHP crypt()
.
Результаты выглядят примерно так:
$1$Vf/.4.1.$CgCo33ebiHVuFhpwS.kMI0
$1$84..vD4.$Ps1PdaLWRoaiWDKCfjLyV1
$1$or1.RY4.$v3xo04v1yfB7JxDj1sC/J/
Хотя я считаю, что crypt () использует алгоритм MD5, выходные данные не являются действительными хэшами MD5.
Есть ли способ преобразования полученных хешей в действительные хеш-коды MD5 (16-байтовые шестнадцатеричные значения)?
<Ч>Update:
Спасибо за ответы, так что ответы до сих пор. Я почти уверен, что используемая функция crypt использует какой-то алгоритм MD5. Что я хочу сделать, так это преобразовать полученный у меня результат в хеш MD5, который выглядит примерно так:
9e107d9d372bb6826bd81d3542a419d6
e4d909c290d0fb1ca068ffaddf22cbd0
d41d8cd98f00b204e9800998ecf8427e
(взято из Википедии )
Есть ли способ конвертировать из хешей, которые у меня есть, в те, что указаны выше?
Решение
Хорошо, возможно, этот ответ опоздал на год, но я попробую. В своем собственном ответе вы заметите, что crypt()
использует FreeBSD MD5, который также выполняет некоторые интересные преобразования в соли перед запуском хэша, поэтому результат, который я собираюсь вам дать, никогда не будет полностью соответствовать результаты звонка на md5()
. Тем не менее, единственная разница между выводом, который вы видите, и форматом, к которому вы привыкли, заключается в том, что вывод, который вы видите, кодируется следующим образом
$1$ # this indicates that it is MD5
Vf/.4.1. # these eight characters are the significant portion of the salt
$ # this character is technically part of the salt, but it is ignored
CgCo33eb # the last 22 characters are the actual hash
iHVuFhpw # they are base64 encoded (to be printable) using crypt's alphabet
S.kMI0 # floor(22 * 6 / 8) = 16 (the length in bytes of a raw MD5 hash)
Насколько мне известно, алфавит, используемый crypt, выглядит следующим образом:
./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
Итак, учитывая все это, вот как вы можете преобразовать 22-значный хэш crypt-base64 в 32-значный base16 (шестнадцатеричный) хеш:
Во-первых, вам нужно что-то, чтобы преобразовать base64 (с пользовательским алфавитом) в необработанный 16-байтовый хеш MD5.
define('CRYPT_ALPHA','./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
/**
* Decodes a base64 string based on the alphabet set in constant CRYPT_ALPHA
* Uses string functions rather than binary transformations, because said
* transformations aren't really much faster in PHP
* @params string $str The string to decode
* @return string The raw output, which may include unprintable characters
*/
function base64_decode_ex($str) {
// set up the array to feed numerical data using characters as keys
$alpha = array_flip(str_split(CRYPT_ALPHA));
// split the input into single-character (6 bit) chunks
$bitArray = str_split($str);
$decodedStr = '';
foreach ($bitArray as &$bits) {
if ($bits == '$') { // $ indicates the end of the string, to stop processing here
break;
}
if (!isset($alpha[$bits])) { // if we encounter a character not in the alphabet
return false; // then break execution, the string is invalid
}
// decbin will only return significant digits, so use sprintf to pad to 6 bits
$decodedStr .= sprintf('%06s', decbin($alpha[$bits]));
}
// there can be up to 6 unused bits at the end of a string, so discard them
$decodedStr = substr($decodedStr, 0, strlen($decodedStr) - (strlen($decodedStr) % 8));
$byteArray = str_split($decodedStr, 8);
foreach ($byteArray as &$byte) {
$byte = chr(bindec($byte));
}
return join($byteArray);
}
Теперь, когда у вас есть необработанные данные, вам понадобится метод для преобразования их в ожидаемый формат base-16, который не может быть проще.
/**
* Takes an input in base 256 and encodes it to base 16 using the Hex alphabet
* This function will not be commented. For more info:
* @see http://php.net/str-split
* @see http://php.net/sprintf
*
* @param string $str The value to convert
* @return string The base 16 rendering
*/
function base16_encode($str) {
$byteArray = str_split($str);
foreach ($byteArray as &$byte) {
$byte = sprintf('%02x', ord($byte));
}
return join($byteArray);
}
Наконец, поскольку выходные данные crypt включают в себя много данных, которые нам не нужны (и фактически не могут использовать) для этого процесса, короткая и приятная функция, которая не только связывает эти два элемента вместе, но и позволяет напрямую ввод вывода из склепа.
/**
* Takes a 22 byte crypt-base-64 hash and converts it to base 16
* If the input is longer than 22 chars (e.g., the entire output of crypt()),
* then this function will strip all but the last 22. Fails if under 22 chars
*
* @param string $hash The hash to convert
* @param string The equivalent base16 hash (therefore a number)
*/
function md5_b64tob16($hash) {
if (strlen($hash) < 22) {
return false;
}
if (strlen($hash) > 22) {
$hash = substr($hash,-22);
}
return base16_encode(base64_decode_ex($hash));
}
Учитывая эти функции, представление base16 ваших трех примеров:
3ac3b4145aa7b9387a46dd7c780c1850
6f80dba665e27749ae88f58eaef5fe84
ec5f74086ec3fab34957d3ef0f838154
Конечно, важно помнить, что они всегда были действительны, просто отформатированы по-разному.
Другие советы
$ 1 $ действительно означает, что это хеш MD5, но crypt генерирует случайную соль. Вот почему вы найдете другое значение MD5. Если вы включите сгенерированную соль, вы найдете тот же результат.
Соль в кодировке base64, как хеш.
Используемый алгоритм является общесистемным параметром. Как правило, это MD5, вы правы.
Я считаю, что ответ на мой первоначальный вопрос - нет, вы не можете конвертировать из одного формата в другой.
Хеши, сгенерированные php crypt (), по-видимому, генерируются версией реализации хэша FreeBSD MD5, созданной Poul-Henning Kamp.
Из документации это зависит от системы. Вы можете принудительно использовать алгоритм, используя параметр соли. Из документов:
Тип шифрования запускается солевой аргумент. Во время установки PHP определяет возможности функция склепа и будет принимать соли для других типов шифрования. Если нет соли при условии, PHP будет автоматически генерировать стандартная двухсимвольная соль по умолчанию, если только шифрование по умолчанию тип в системе MD5, в котором случай случайной MD5-совместимой соли генерируется. р>
От http://php.net/crypt :
crypt () вернет зашифрованную строку, используя стандартный алгоритм шифрования на основе DES Unix или альтернативные алгоритмы, которые могут быть доступны в системе.
Вам нужна md5()
функция:
Вычисляет MD5-хеш str, используя & # 187; RSA Data Security, Inc. Алгоритм дайджеста сообщений MD5 и возвращает этот хеш.
Если для необязательного raw_output установлено значение TRUE, вместо этого возвращается дайджест md5 в необработанном двоичном формате длиной 16. По умолчанию FALSE. Р>