Можете ли вы преобразовать вывод php crypt () в действительный MD5?

у меня есть некоторые строки, которые были зашифрованы с помощью функции PHP crypt().

результаты выглядят примерно так:

$Vf/.4.1.$CgCo33ebiHVuFhpwS.kMI0
..vD4.$Ps1PdaLWRoaiWDKCfjLyV1
$or1.RY4.$v3xo04v1yfB7JxDj1sC/J/

хотя я считаю, что crypt () использует алгоритм MD5, выходы не являются допустимыми хэшами MD5.

есть ли способ преобразования произведенных хэшей в действительные хэши MD5 (16-байтовые шестнадцатеричные значения)?


обновление:

Спасибо за ответы так ответы далеко. Я уверен, что используемая функция crypt использует какой-то алгоритм MD5. То, что я хочу сделать, это преобразовать вывод, который у меня есть, в хэш MD5, который выглядит примерно так:

9e107d9d372bb6826bd81d3542a419d6  
e4d909c290d0fb1ca068ffaddf22cbd0  
d41d8cd98f00b204e9800998ecf8427e

(взято из Википедия)

есть ли способ конверсии хэши у меня, как выше?

5 ответов


хорошо, может быть, этот ответ на год опоздал,но я попробую. В своем собственном ответе вы отмечаете, что crypt() использует FreeBSD MD5, который также выполняет некоторые интересные преобразования в соли перед запуском хэша, поэтому результат того, что я собираюсь дать вам, никогда не будет полностью соответствовать результатам вызова md5(). Тем не менее, только разница между выходными вы видите и формата вы привыкли к тому, что на выходе вы видите кодируется как следует

$        # 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)

насколько мне известно, алфавит, используемый криптой, выглядит так:

./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 включает в себя много данных, которые нам не нужны (и, по сути, не могут использоваться) для этого процесса, короткая и сладкая функция не только связать эти два вместе, но и разрешить прямой ввод вывода из 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.

http://people.freebsd.org/~phk/


из документации, это зависит от системы. Можно принудительно использовать алгоритм, задав параметр salt. Из документов:

тип шифрования запускается спор о соли. Во время установки, PHP определяет возможности функция crypt и будет принимать соли для других типов шифрования. Если нет соли предоставляется, PHP будет автоматически генерировать соль характера стандарта 2 мимо по умолчанию, если не шифрование по умолчанию типа на система MD5, в которой случайная MD5-совместимая соль сгенерированный.


от http://php.net/crypt:

crypt () вернет зашифрованную строку, используя стандартный алгоритм шифрования на основе Unix DES или альтернативные алгоритмы, которые могут быть доступны в системе.

вы хотите md5():

вычисляет хэш MD5 str, используя " RSA Data Security, Inc. MD5 Message-алгоритм дайджеста и возвращает этот хэш.
Если необязательный raw_output имеет значение TRUE, а затем дайджест md5 возвращается в двоичном формате raw с длиной 16. По умолчанию установлено значение FALSE.