17

この関数の基本を理解する必要があります。php.net のドキュメントには、blowfish アルゴリズムについて次のように記載されています。

「$2a$」、2 桁のコスト パラメータ、「$」、およびアルファベットの 22 個の base 64 桁「./0-9A-Za-z」のソルトを使用したフグのハッシュ。ソルトでこの範囲外の文字を使用すると、crypt() は長さゼロの文字列を返します。

したがって、これは定義上、機能しないはずです。

echo crypt('rasmuslerdorf', '$2a$07$usesomadasdsadsadsadasdasdasdsadesillystringforsalt$');

ただし、次のように吐き出します。

$2a$07$usesomadasdsadsadsadaeMTUHlZEItvtV00u0.kb7qhDlC0Kou9e

crypt() がソルト自体を 22 の長さにカットしたように見える場所。誰かがこれを説明してくれませんか?

私が理解できないこの関数の別の側面は、crypt() を使用してパスワードを比較する場合です。http://php.net/manual/en/function.crypt.php (例 #1 を参照)。これは、すべてのパスワードを暗号化するために同じソルトを使用する場合、最初に暗号化する必要があるということですか? すなわち:

$salt = "usesomadasdsadsadsadae";
$salt_crypt = crypt($salt);

if (crypt($user_input, $salt) == $password) {
   // FAIL WONT WORK
}

if (crypt($user_input, $salt_crypt) == $password) {
   // I HAVE TO DO THIS?
}    

御時間ありがとうございます

4

6 に答える 6

22

次のコード例は、あなたの質問に答えるかもしれません。

Blowfish を使用してハッシュ化されたパスワードを生成するには、最初にソルトを生成する必要があります。ソルトは $2a$ で始まり、その後に繰り返し回数と 22 文字の Base64 文字列が続きます。

$salt = '$2a$07$usesomadasdsadsadsadasdasdasdsadesillystringfors';
$digest = crypt('rasmuslerdorf', $salt);

$digest 全体をデータベースに保存します。ソルトとダイジェストの両方があります。

パスワードを比較するときは、これを行うだけで、

  if (crypt($user_input, $digest) == $digest)

消化物を塩として再利用しています。crypt は、アルゴリズム識別子からのソルトの長さを知っています。

于 2010-06-28T21:16:22.673 に答える
4

すべてのパスワードの新しいソルト

$password = 'p@ssw0rd';

$salt = uniqid('', true);
$algo = '6'; // CRYPT_SHA512
$rounds = '5042';
$cryptSalt = '$'.$algo.'$rounds='.$rounds.'$'.$salt;

$hashedPassword = crypt($password, $cryptSalt);
// Store complete $hashedPassword in DB

echo "<hr>$password<hr>$algo<hr>$rounds<hr>$cryptSalt<hr>$hashedPassword";

認証

if (crypt($passwordFromPost, $hashedPasswordInDb) == $hashedPasswordInDb) {
    // Authenticated
于 2013-03-27T13:07:11.683 に答える
2

マニュアルからの引用

CRYPT_BLOWFISH-次のようにソルトを使用したBlowfishハッシュ: "$ 2a $"、2桁のコストパラメータ "$"、およびアルファベットからの22のbase64桁

注:22ベース64桁

于 2010-06-28T19:44:39.207 に答える
2

BCrypt はソルトに 128 ビットを使用するため、22 バイトの Base64 が使用され、最後のバイトの 2 ビットのみが使用されます。

ハッシュはソルトとパスワードを使用して計算されます。暗号化されたパスワードを渡すと、アルゴリズムは強度、salt (それ以降はすべて無視)、および指定したパスワードを読み取り、ハッシュを計算して追加します。PostgreSQL と pg_crypto が手元にある場合は、SELECT gen_salt('bf'); を実行します。$salt の何が読み取られているかを表示します。

これは、私の.NET 実装の test-vector-gen.phpからのソルト生成のコード サンプルです。

$salt = sprintf('$2a$%02d$%s', [strength goes here],
    strtr(str_replace(
    '=', '', base64_encode(openssl_random_pseudo_bytes(16))
    ),
    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
    './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'));

すべてのパスワードに同じソルトを使用する理由はありません。とにかくソルトは出力の一部であるため、利便性は何も得られません... ただし、PHPには組み込みの gen_salt 関数が必要です。

于 2011-01-22T17:08:08.423 に答える
0

最初の質問:

したがって、これは、定義上、機能しないはずです。

echo crypt('rasmuslerdorf', '$2a$07$usesomadasdsadsadsadasdasdasdsadesillystringforsalt$');

crypt()がソルト自体を22の長さにカットしたように見えるところ。誰かがこれを説明してもらえますか?

文字が多すぎても問題はありません...ソルトでこの範囲外の文字を使用すると、crypt()は、 22の範囲ではなくbase64の範囲外を参照する長さゼロの文字列を返します。文字。ソルト文字列に不正な文字を入れてみてください。空の出力が得られるはずです(または、22文字未満を入れると、不正な空のバイトになります)。

2番目の質問:

ソルト文字列は常に暗号化された文字列に(設計上)表示されるため、暗号化された保存済みパスワードをソルトとして渡します。これにより、保存済みパスワードとユーザー入力パスワードの両方の暗号化で同じソルトを使用できるようになります。

于 2010-06-28T19:47:54.523 に答える
0

この質問は、ZZCoderの回答に対する私の回答に関連しています。基本的に私の質問は、crypt()の結果をデータベースに保存することに関するものです。私のデータベースが次のようになるように、出力全体をデータベースに保存することになっていますか?

--------------------------------------------------------------------------------
| ID | Username |                          Password                            |
--------------------------------------------------------------------------------
| 32 | testuser | $2a$07$usesomadasdsadsadsadaeMTUHlZEItvtV00u0.kb7qhDlC0Kou9e |
--------------------------------------------------------------------------------

もしそうなら、そもそもこの種の塩を使うという目的に逆らうのではないでしょうか?誰かがデータベースにアクセスした場合、暗号化に使用されたソルトをはっきりと見ることができますか?

ボーナスの質問:すべてのパスワードに同じソルトを使用するのは安全ですか?

于 2010-06-29T20:54:03.140 に答える