你可以将php crypt()的输出转换为有效的MD5吗? [英] Can you convert the output of php crypt() to valid MD5?

查看:154
本文介绍了你可以将php crypt()的输出转换为有效的MD5吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些使用 PHP函数 crypt()



输出看起来像这样:

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

虽然我相信crypt()使用MD5算法,但输出不是有效的MD5哈希值。



有没有一种方法将生成的散列转换为有效的MD5哈希值(16字节十六进制值)?






更新:



感谢回复,所以回答到目前为止。我很确定所使用的crypt函数是使用某种MD5算法。我想要做的是将输出转换为MD5哈希,看起来像下面:

  9e107d9d372bb6826bd81d3542a419d6 
e4d909c290d0fb1ca068ffaddf22cbd0
d41d8cd98f00b204e9800998ecf8427e

(取自 Wikipedia



有办法

$ p

解决方案

确定,所以也许这个答案是一年晚了,但是,我会给它一枪。在你自己的回答中,你注意到 crypt()正在使用FreeBSD MD5,它在运行哈希之前对盐进行一些有趣的转换,所以结果是什么'm将给你永远不会匹配到调用 md5()的结果。也就是说,你看到的输出和你习惯的格式之间的唯一区别是你看到的输出编码如下

  $ 1 $#这表示它是MD5 
Vf / .4.1。 #这八个字符是盐的重要部分
$#这个字符在技术上是盐的一部分,但它被忽略
CgCo33eb#最后22个字符是实际的哈希
iHVuFhpw#它们使用crypt的字母表进行base64编码(可打印)
S.kMI0#floor(22 * 6/8)= 16(原始MD5散列的字节长度)
 > 。/ 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 

所以,是如何将22个字符crypt-base64哈希转换为32个字符base16(十六进制)哈希:



首先,需要一些东西来转换base64 )转换为原始的16位元MD5哈希值。

  define('CRYPT_ALPHA','。/ 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'); 
/ **
*基于在常量CRYPT_ALPHA中设置的字母表解码base64字符串
*使用字符串函数而不是二进制转换,因为所述
*转换不是很多更快的PHP
* @params string $ str要解码的字符串
* @return string原始输出,可能包含不可打印的字符
* /
function base64_decode_ex($ str) {
//设置数组,使用字符作为键来输入数字数据
$ alpha = array_flip(str_split(CRYPT_ALPHA));
//将输入分成单字符(6位)块
$ bitArray = str_split($ str);
$ decodedStr ='';
foreach($ bitArray as& $ bits){
if($ bits =='$'){// $表示字符串的结尾,停止处理
break;
}
if(!isset($ alpha [$ bits])){//如果我们遇到字符不在字母表中
return false; //然后断点执行,字符串无效
}
// decbin只返回有效数字,所以使用sprintf填充6位
$ decodedStr。= sprintf('%06s' ,decbin($ alpha [$ bits]));
}
//在字符串末尾最多可以有6个未使用的位,因此丢弃它们
$ 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);
}

现在您已经获得了原始数据,将它转换为您期望的基本16格式,这不容易。

  / ** 
*使用基本256输入,并使用十六进制字母将其编码为基本16
*此函数不会被注释。更多信息:
* @see http://php.net/str-split
* @see http://php.net/sprintf
*
* @param string $ str要转换的值
* @return string基本16渲染
* /
函数base16_encode($ str){
$ byteArray = str_split($ str);
foreach($ byteArray as& $ byte){
$ byte = sprintf('%02x',ord($ byte));
}
return join($ byteArray);
}



最后,由于crypt的输出包含大量数据需要(而且,事实上,不能使用)这个过程,一个短而甜的功能,不仅将这两个一起,但允许直接输入crypt的输出。

  / ** 
*获取一个22字节的crypt-base-64散列并将其转换为基础16
*如果输入长度超过22个字符,crypt()的整个输出),
*然后这个函数将剥离所有除了最后22.如果在22个字符以下失败
*
* @param string $ hash要转换的哈希
* @param string等效的base16哈希值(因此为数字)
* /
函数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

当然,重要的是要记住,他们总是有效,只是格式不同。


I have some strings that have been encrypted using the PHP function crypt().

The outputs look something like this:

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

While I believe crypt() is using the MD5 algorithm, the outputs are not valid MD5 hashes.

Is there a way of converting the produced hashes into valid MD5 hashes (16-byte hex values)?


Update:

Thanks for the replies so answers so far. I'm pretty sure the crypt function used is using some sort of MD5 algorithm. What I'm looking to do is convert the ouput that I have into an MD5 hash that looks something like the following:

9e107d9d372bb6826bd81d3542a419d6  
e4d909c290d0fb1ca068ffaddf22cbd0  
d41d8cd98f00b204e9800998ecf8427e

(taken from Wikipedia)

Is there a way of converting from the hashes I have to ones like the above?

解决方案

OK, so maybe this answer is a year late, but I'll give it a shot. In your own answer, you note that crypt() is using the FreeBSD MD5, which also does some interesting transformations on the salt before running the hash, so the result of what I'm about to give you will never quite match up with the results of a call to md5(). That said, the only difference between the output you are seeing and the format you are used to is that the output you are seeing is encoded as follows

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

To my knowledge, the alphabet used by crypt looks like this:

./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz

So, with all of this borne in mind, here is how you can convert the 22 character crypt-base64 hash into a 32 character base16 (hexadecimal) hash:

First, you need something to convert the base64 (with custom alphabet) into a raw 16-byte MD5 hash.

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

Now that you've got the raw data, you'll need a method to convert it to the base-16 format you're expecting, which couldn't be easier.

/**
 * 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);
}

Finally, since the output of crypt includes a lot of data we don't need (and, in fact, cannot use) for this process, a short and sweet function to not only tie these two together but to allow for direct input of output from 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));
}

Given these functions, the base16 representation of your three examples are:

3ac3b4145aa7b9387a46dd7c780c1850
6f80dba665e27749ae88f58eaef5fe84
ec5f74086ec3fab34957d3ef0f838154

Of course, it is important to remember that they were always valid, just formatted differently.

这篇关于你可以将php crypt()的输出转换为有效的MD5吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆