6

PHP関数crypt()を使用して暗号化された文字列がいくつかあります。

出力は次のようになります。

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

crypt()はMD5アルゴリズムを使用していると思いますが、出力は有効なMD5ハッシュではありません。

生成されたハッシュを有効なMD5ハッシュ(16バイトの16進値)に変換する方法はありますか?


アップデート:

返信ありがとうございますので、これまでの回答。使用されているcrypt関数は、ある種のMD5アルゴリズムを使用していると確信しています。私が探しているのは、私が持っている出力を次のようなMD5ハッシュに変換することです。

9e107d9d372bb6826bd81d3542a419d6  
e4d909c290d0fb1ca068ffaddf22cbd0  
d41d8cd98f00b204e9800998ecf8427e

ウィキペディアから取得)

私が持っているハッシュから上記のようなハッシュに変換する方法はありますか?

4

5 に答える 5

9

わかりましたので、この回答は 1 年遅れているかもしれませんが、試してみます。あなた自身の答えで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 (16 進数) ハッシュに変換する方法を次に示します。

まず、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 の出力には、このプロセスには必要のない (そして実際には使用できない) 大量のデータが含まれているため、これら 2 つを結び付けるだけでなく、出力の直接入力を可能にする短くて便利な関数を使用します。クリプトから。

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

これらの関数を考えると、3 つの例の base16 表現は次のようになります。

3ac3b4145aa7b9387a46dd7c780c1850
6f80dba665e27749ae88f58eaef5fe84
ec5f74086ec3fab34957d3ef0f838154

もちろん、フォーマットが異なるだけで、常に有効であることを覚えておくことは重要です。

于 2010-02-10T15:05:11.593 に答える
2

$ 1 $は確かに、これがMD5ハッシュであることを意味しますが、cryptはランダムなソルトを生成します。これが、異なるMD5値を見つける理由です。生成されたソルトを含めると、同じ結果が得られます。

ソルトは、ハッシュとして出力でbase64エンコードされます。

使用されるアルゴリズムは、システム全体のパラメーターです。一般的にこれはMD5です、あなたは正しいです。

于 2009-01-20T15:50:38.840 に答える
2

元の質問に対する答えはノーだと思います。ある形式から別の形式に変換することはできません。

php crypt() によって生成されるハッシュは、Poul-Henning Kamp によって作成された FreeBSD MD5 ハッシュ実装のバージョンによって生成されるようです。

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

于 2009-01-21T16:02:31.453 に答える
0

ドキュメントから、これはシステムによって異なります。saltパラメータを設定することで、使用するアルゴリズムを強制できます。ドキュメントから:

暗号化タイプはsalt引数によってトリガーされます。インストール時に、PHPはcrypt関数の機能を決定し、他の暗号化タイプのソルトを受け入れます。ソルトが提供されていない場合、システムのデフォルトの暗号化タイプがMD5である場合を除き、PHPはデフォルトで標準の2文字のソルトを自動生成します。MD5の場合、ランダムなMD5互換のソルトが生成されます。

于 2009-01-20T15:47:22.967 に答える
0

http://php.net/cryptから:

crypt()は、標準のUnixDESベースの暗号化アルゴリズムまたはシステムで使用可能な代替アルゴリズムを使用して暗号化された文字列を返します。

md5()次の関数が必要です。

»RSADataSecurity、Inc.のMD5メッセージダイジェストアルゴリズムを使用してstrのMD5ハッシュを計算し、そのハッシュを返します。
オプションのraw_outputがTRUEに設定されている場合、md5ダイジェストは代わりに長さ16のrawバイナリ形式で返されます。デフォルトはFALSEです。

于 2009-01-20T15:49:28.343 に答える