سؤال

لدي بعض الأوتار التي تم تشفيرها باستخدام وظيفة PHP crypt().

تبدو المخرجات شيئًا من هذا القبيل:

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

على الرغم من أنني أعتقد أن Crypt () يستخدم خوارزمية MD5 ، فإن المخرجات غير صالحة لتجزئة MD5.

هل هناك طريقة لتحويل التجزئة المنتجة إلى تجزئة MD5 صالحة (قيم سداسية عشرية 16 بايت)؟


تحديث:

شكرا على الردود حتى يجيب حتى الآن. أنا متأكد من أن وظيفة Crypt المستخدمة تستخدم نوعًا من خوارزمية MD5. ما أتطلع إلى فعله هو تحويل OUPUT الذي لدي إلى تجزئة 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)

على حد علمي ، فإن الأبجدية المستخدمة من قبل سرداب تبدو مثل هذا:

./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz

لذا ، مع وضع كل هذا في الاعتبار ، إليك كيفية تحويل تجزئة الحرف 22 Crypt-Base64 إلى تجزئة 32 حرفًا (سداسي عشري):

أولاً ، تحتاج إلى شيء لتحويل Base64 (مع الأبجدية المخصصة) إلى تجزئة MD5 الخام 16 بايت.

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.

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

من الوثائق ، هذا يعتمد على النظام. يمكنك فرض الخوارزمية المستخدمة عن طريق ضبط معلمة الملح. من المستندات:

يتم تشغيل نوع التشفير بواسطة حجة الملح. في وقت التثبيت ، تحدد PHP قدرات وظيفة crypt وسوف تقبل الأملاح لأنواع التشفير الأخرى. إذا لم يتم توفير ملح ، فسيقوم PHP بتوظيف ملح شخصي قياسي من الحرف بشكل افتراضي ، ما لم يكن نوع التشفير الافتراضي على النظام هو MD5 ، وفي هذه الحالة يتم إنشاء ملح عشوائي متوافق مع MD5.

من http://php.net/crypt:

ستعيد Crypt () سلسلة مشفرة باستخدام خوارزمية التشفير القياسية UNIX DES أو خوارزميات بديلة قد تكون متوفرة على النظام.

تريد md5() وظيفة:

يحسب علامة التجزئة MD5 لـ STR باستخدام خوارزمية MD5 Data Security ، Inc. MD5 ، وإرجاع هذا التجزئة.
إذا تم تعيين RAW_OUTPUT الاختياري على TRUE ، فسيتم إرجاع MD5 Digest بدلاً من ذلك بتنسيق ثنائي RAW بطول 16. الافتراضيات إلى False.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top