1315

「PHP にパスワードを保存するために bcrypt を使用する、bcrypt ルール」というアドバイスを時々耳にします。

しかし、何bcryptですか?PHP にはそのような機能はありません。ウィキペディアではファイル暗号化ユーティリティについてうわさ話をし、Web 検索ではさまざまな言語でのBlowfishの実装がいくつか明らかになるだけです。現在、Blowfish は 経由で PHP からも利用できますがmcrypt、これはパスワードの保存にどのように役立つのでしょうか? Blowfish は汎用暗号であり、2 つの方法で機能します。暗号化できれば、復号化できます。パスワードには一方向ハッシュ関数が必要です。

説明は何ですか?

4

11 に答える 11

1100

bcrypt(構成可能なラウンド数を介して) ハードウェアで拡張可能なハッシュ アルゴリズムです。その遅さと複数のラウンドにより、攻撃者はパスワードをクラックできるようにするために膨大な資金とハードウェアを展開する必要があります. そのパスワードごとのソルト(bcryptソルトが必要) に追加すると、ばかげた金額の資金やハードウェアがなければ、攻撃は事実上実行不可能であると確信できます。

bcryptEksblowfishアルゴリズムを使用してパスワードをハッシュします。EksblowfishBlowfishの暗号化フェーズはまったく同じですが、 Eksblowfishのキー スケジュール フェーズでは、後続の状態がソルトとキー (ユーザー パスワード) の両方に依存し、両方の知識がなければ状態を事前に計算することはできません。この重要な違いにより、bcryptは一方向ハッシュ アルゴリズムです。ソルト、ラウンド、およびキー(パスワード)を知らなければ、平文のパスワードを取得することはできません。【ソース

bcrypt の使用方法:

PHP >= 5.5-DEV の使用

パスワード ハッシュ関数は、PHP >= 5.5 に直接組み込まれました。任意のパスワードのハッシュpassword_hash()を作成するために使用できるようになりました。bcrypt

<?php
// Usage 1:
echo password_hash('rasmuslerdorf', PASSWORD_DEFAULT)."\n";
// $2y$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// For example:
// $2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

// Usage 2:
$options = [
  'cost' => 11
];
echo password_hash('rasmuslerdorf', PASSWORD_BCRYPT, $options)."\n";
// $2y$11$6DP.V0nO7YI3iSki4qog6OQI5eiO6Jnjsqg7vdnb.JgGIsxniOn4C

ユーザーが提供したパスワードを既存のハッシュに対して検証するには、次のpassword_verify()ように使用できます。

<?php
// See the password_hash() example to see where this came from.
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';

if (password_verify('rasmuslerdorf', $hash)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}

PHP >= 5.3.7、< 5.5-DEV を使用 (RedHat PHP >= 5.3.3 も)

GitHubには、C で記述された上記の関数のソース コードに基づいて作成された互換ライブラリがあり、同じ機能を提供します互換性ライブラリがインストールされると、使用方法は上記と同じになります (まだ 5.3.x ブランチを使用している場合は、省略形の配列表記を除きます)。

PHP < 5.3.7 (非推奨)の使用

関数を使用crypt()して、入力文字列の bcrypt ハッシュを生成できます。このクラスは自動的にソルトを生成し、入力に対して既存のハッシュを検証できます。5.3.7 以降のバージョンの PHP を使用している場合は、組み込み関数または互換ライブラリを使用することを強くお勧めします。この代替手段は、歴史的な目的のためにのみ提供されています。

class Bcrypt{
  private $rounds;

  public function __construct($rounds = 12) {
    if (CRYPT_BLOWFISH != 1) {
      throw new Exception("bcrypt not supported in this installation. See http://php.net/crypt");
    }

    $this->rounds = $rounds;
  }

  public function hash($input){
    $hash = crypt($input, $this->getSalt());

    if (strlen($hash) > 13)
      return $hash;

    return false;
  }

  public function verify($input, $existingHash){
    $hash = crypt($input, $existingHash);

    return $hash === $existingHash;
  }

  private function getSalt(){
    $salt = sprintf('$2a$%02d$', $this->rounds);

    $bytes = $this->getRandomBytes(16);

    $salt .= $this->encodeBytes($bytes);

    return $salt;
  }

  private $randomState;
  private function getRandomBytes($count){
    $bytes = '';

    if (function_exists('openssl_random_pseudo_bytes') &&
        (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { // OpenSSL is slow on Windows
      $bytes = openssl_random_pseudo_bytes($count);
    }

    if ($bytes === '' && is_readable('/dev/urandom') &&
       ($hRand = @fopen('/dev/urandom', 'rb')) !== FALSE) {
      $bytes = fread($hRand, $count);
      fclose($hRand);
    }

    if (strlen($bytes) < $count) {
      $bytes = '';

      if ($this->randomState === null) {
        $this->randomState = microtime();
        if (function_exists('getmypid')) {
          $this->randomState .= getmypid();
        }
      }

      for ($i = 0; $i < $count; $i += 16) {
        $this->randomState = md5(microtime() . $this->randomState);

        if (PHP_VERSION >= '5') {
          $bytes .= md5($this->randomState, true);
        } else {
          $bytes .= pack('H*', md5($this->randomState));
        }
      }

      $bytes = substr($bytes, 0, $count);
    }

    return $bytes;
  }

  private function encodeBytes($input){
    // The following is code from the PHP Password Hashing Framework
    $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

    $output = '';
    $i = 0;
    do {
      $c1 = ord($input[$i++]);
      $output .= $itoa64[$c1 >> 2];
      $c1 = ($c1 & 0x03) << 4;
      if ($i >= 16) {
        $output .= $itoa64[$c1];
        break;
      }

      $c2 = ord($input[$i++]);
      $c1 |= $c2 >> 4;
      $output .= $itoa64[$c1];
      $c1 = ($c2 & 0x0f) << 2;

      $c2 = ord($input[$i++]);
      $c1 |= $c2 >> 6;
      $output .= $itoa64[$c1];
      $output .= $itoa64[$c2 & 0x3f];
    } while (true);

    return $output;
  }
}

このコードは次のように使用できます。

$bcrypt = new Bcrypt(15);

$hash = $bcrypt->hash('password');
$isGood = $bcrypt->verify('password', $hash);

または、 Portable PHP Hashing Frameworkを使用することもできます。

于 2011-06-13T22:11:39.987 に答える
307

それで、あなたはbcryptを使いたいですか?素晴らしい!ただし、暗号化の他の分野と同様に、自分で行うべきではありません。キーの管理、ソルトの保存、乱数の生成などについて心配する必要がある場合は、それが間違っています。

理由は簡単です: bcryptを台無しにするのは簡単です。実際、このページのほぼすべてのコードを見ると、これらの一般的な問題の少なくとも 1 つに違反していることに気付くでしょう。

直面してください、暗号化は難しいです。

専門家に任せましょう。これらのライブラリを維持する仕事をしている人々に任せてください。決定を下す必要がある場合、それは間違っています。

代わりに、ライブラリを使用してください。要件に応じていくつか存在します。

ライブラリ

以下は、より一般的な API の一部の内訳です。

PHP 5.5 API - (5.3.7 以降で利用可能)

PHP 5.5 以降では、パスワードをハッシュするための新しい API が導入されています。5.3.7+ 用に (私が) 保守している shim 互換ライブラリもあります。これには、査読済みで使いやすい実装であるという利点があります

function register($username, $password) {
    $hash = password_hash($password, PASSWORD_BCRYPT);
    save($username, $hash);
}

function login($username, $password) {
    $hash = loadHashByUsername($username);
    if (password_verify($password, $hash)) {
        //login
    } else {
        // failure
    }
}

本当に、それは非常に単純であることを目指しています。

資力:

Zend\Crypt\Password\Bcrypt (5.3.2 以降)

これは、PHP 5.5 の API に似た別の API で、同様の目的を果たします。

function register($username, $password) {
    $bcrypt = new Zend\Crypt\Password\Bcrypt();
    $hash = $bcrypt->create($password);
    save($user, $hash);
}

function login($username, $password) {
    $hash = loadHashByUsername($username);
    $bcrypt = new Zend\Crypt\Password\Bcrypt();
    if ($bcrypt->verify($password, $hash)) {
        //login
    } else {
        // failure
    }
}

資力:

PasswordLib

これは、パスワード ハッシュとは少し異なるアプローチです。単純に bcrypt をサポートするのではなく、PasswordLib は多数のハッシュ アルゴリズムをサポートします。これは主に、制御できないレガシー システムや異種システムとの互換性をサポートする必要がある場合に役立ちます。多数のハッシュアルゴリズムをサポートしています。および 5.3.2 以降がサポートされています

function register($username, $password) {
    $lib = new PasswordLib\PasswordLib();
    $hash = $lib->createPasswordHash($password, '$2y$', array('cost' => 12));
    save($user, $hash);
}

function login($username, $password) {
    $hash = loadHashByUsername($username);
    $lib = new PasswordLib\PasswordLib();
    if ($lib->verifyPasswordHash($password, $hash)) {
        //login
    } else {
        // failure
    }
}

参考文献:

  • ソースコード/ドキュメント: GitHub

PHPASS

これは bcrypt をサポートするレイヤーですが、PHP >= 5.3.2 にアクセスできない場合に役立つかなり強力なアルゴリズムもサポートしています... 実際には PHP 3.0+ をサポートしています (bcrypt はサポートしていません)。

function register($username, $password) {
    $phpass = new PasswordHash(12, false);
    $hash = $phpass->HashPassword($password);
    save($user, $hash);
}

function login($username, $password) {
    $hash = loadHashByUsername($username);
    $phpass = new PasswordHash(12, false);
    if ($phpass->CheckPassword($password, $hash)) {
        //login
    } else {
        // failure
    }
}

資力

注: Openwall でホストされていない PHPASS の代替案は使用しないでください。それらは別のプロジェクトです!!!

Bクリプトについて

お気づきのとおり、これらのライブラリはすべて 1 つの文字列を返します。これは、BCrypt が内部でどのように機能するかによるものです。そして、それについてはたくさんの答えがあります。これは私が書いたものです。ここではコピー/貼り付けはしませんが、リンクは次のとおりです。

要約

多くの異なる選択肢があります。どちらを選択するかはあなた次第です。ただし、これを処理するために上記のライブラリのいずれかを使用することを強くお勧めします。

繰り返しますが、crypt()直接使用している場合は、おそらく何か間違ったことをしている可能性があります。コードでhash()(またはmd5()またはsha1()) を直接使用している場合、ほぼ間違いなく何か間違ったことをしています。

ライブラリを使用するだけで...

于 2013-06-12T19:23:21.677 に答える
47

Enough With The Rainbow Tables: What You Need To Know About Secure Password SchemesまたはPortable PHP password hashing frameworkで多くの情報を得ることができます。

目標は、何か遅いものでパスワードをハッシュすることです。そのため、誰かがあなたのパスワード データベースをブルート フォースしようとして死んでしまいます (パスワードをチェックするための 10 ミリ秒の遅延は、あなたにとっては何の役にも立ちません。Bcryptは低速で​​あり、パラメータを使用して速度を選択できます。

于 2011-01-25T15:46:48.830 に答える
36

PHP の関数を使用して bcrypt で一方向ハッシュを作成crypt()し、適切な Blowfish ソルトを渡すことができます。方程式全体の中で最も重要なのは、A) アルゴリズムが侵害されていないこと、および B)各パスワードを適切にソルトすることです。アプリケーション全体のソルトを使用しないでください。これにより、アプリケーション全体が単一の Rainbow テーブル セットから攻撃できるようになります。

PHP-暗号機能

于 2011-01-25T15:48:37.270 に答える
34

編集: 2013.01.15 - サーバーがサポートしている場合は、代わりにmartinstoeckli のソリューションを使用してください。


誰もがこれを実際よりも複雑にしたいと考えています。crypt() 関数がほとんどの作業を行います。

function blowfishCrypt($password,$cost)
{
    $chars='./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    $salt=sprintf('$2y$%02d$',$cost);
//For PHP < PHP 5.3.7 use this instead
//    $salt=sprintf('$2a$%02d$',$cost);
    //Create a 22 character salt -edit- 2013.01.15 - replaced rand with mt_rand
    mt_srand();
    for($i=0;$i<22;$i++) $salt.=$chars[mt_rand(0,63)];
    return crypt($password,$salt);
}

例:

$hash=blowfishCrypt('password',10); //This creates the hash
$hash=blowfishCrypt('password',12); //This creates a more secure hash
if(crypt('password',$hash)==$hash){ /*ok*/ } //This checks a password

当たり前のことですが、「password」をパスワードとして使用しないでください。

于 2012-10-31T08:25:46.587 に答える
29

PHP のバージョン 5.5 には、BCrypt、関数password_hash()password_verify(). 実際には、これらは function の単なるラッパーでcrypt()あり、正しく使用しやすくします。安全なランダム ソルトの生成を処理し、適切なデフォルト値を提供します。

この関数を使用する最も簡単な方法は次のとおりです。

$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

このコードは、BCrypt (アルゴリズム2y) を使用してパスワードをハッシュし、OS のランダム ソースからランダムなソルトを生成し、既定のコスト パラメーター (現時点では 10) を使用します。2 行目は、ユーザーが入力したパスワードが既に保存されているハッシュ値と一致するかどうかを確認します。

コスト パラメータを変更する必要がある場合は、次のように変更できます。コスト パラメータを 1 増やすと、ハッシュ値の計算に必要な時間が 2 倍になります。

$hash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 11));

パラメーターとは対照的に、関数は暗号的に安全なソルトを作成するために既に最善を尽くしているため、パラメーター"cost"を省略するのが最善です。"salt"

PHP バージョン 5.3.7 以降の場合、関数を作成したのと同じ作者による互換性パックが存在しpassword_hash()ます。5.3.7 より前のバージョンの PHPでは、Unicode に安全な BCrypt アルゴリズムであるcrypt()withがサポートされていません。代わりに、以前の PHP バージョンの最良の代替手段である に2y置き換えることができます。2a

于 2013-01-11T08:07:00.497 に答える
7

現在の考え方: ハッシュは可能な限り最速ではなく、利用可能な中で最も低速であるべきです。これにより、レインボー テーブルアタックが抑制されます。

これも関連しますが、予防策として: 攻撃者がログイン画面に無制限にアクセスすることは決してありません。これを防ぐには: すべてのヒットを URI とともに記録する IP アドレス追跡テーブルを設定します。任意の 5 分間に同じ IP アドレスから 5 回を超えるログイン試行が行われた場合は、説明を付けてブロックします。2 番目のアプローチは、銀行のように 2 層のパスワード スキームを使用することです。2 番目のパスで障害に対するロックアウトを設定すると、セキュリティが強化されます。

概要: 時間のかかるハッシュ関数を使用して攻撃者を遅らせます。また、ログインへのアクセスが多すぎるのをブロックし、2 番目のパスワード階層を追加します。

于 2011-12-07T20:56:55.660 に答える
4

OAuth 2パスワードの場合:

$bcrypt = new \Zend\Crypt\Password\Bcrypt;
$bcrypt->create("youpasswordhere", 10)
于 2016-03-25T16:55:30.457 に答える
3

パスワードを平文でデータベースに保存することは安全ではありません。bcrypt はパスワードのハッシュ技術であり、パスワード セキュリティを構築するために使用されます。bcrypt の驚くべき機能の 1 つは、パスワードが bcrypted 形式で保存されるため、パスワードをハッキング攻撃から保護するために使用されるハッカーから私たちを救うことです。

このpassword_hash()関数は、新しいパスワード ハッシュを作成するために使用されます。強力で堅牢なハッシュ アルゴリズムを使用します。関数はpassword_hash()関数と非常に互換性がありcrypt()ます。したがって、 によって作成されたパスワード ハッシュcrypt()は で使用できpassword_hash()、その逆も可能です。関数password_verify()と関数password_hash()のラッパーだけで、crypt()正確に使用するのがはるかに簡単になります。

構文

string password_hash($password, $algo, $options)

password_hash()次のアルゴリズムは、関数によって現在サポートされています。

  • PASSWORD_DEFAULT
  • PASSWORD_BCRYPT
  • PASSWORD_ARGON2I
  • PASSWORD_ARGON2ID

パラメーター: この関数は、上記および以下で説明する 3 つのパラメーターを受け入れます。

$password: ユーザーのパスワードを格納します。

$algo: パスワードのハッシュ化が行われるときに使用されるアルゴリズムを示しながら、継続的に使用されるパスワード アルゴリズム定数です。

$options: オプションを含む連想配列です。これが削除されて含まれていない場合、ランダムなソルトが使用され、デフォルト コストの使用が発生します。

戻り値: 成功した場合はハッシュ化されたパスワードを返し、失敗した場合は False を返します。

入力:

echo password_hash("GFG@123", PASSWORD_DEFAULT);

出力:

$2y$10$.vGA19Jh8YrwSJFDodbfoHJIOFH)DfhuofGv3Fykk1a

以下のプログラムはpassword_hash()、PHP での関数を示しています。

<?php echo password_hash("GFG@123", PASSWORD_DEFAULT); ?>

出力

$2y$10$Z166W1fBdsLcXPVQVfPw/uRq1ueWMA6sLt9bmdUFz9AmOGLdM393G
于 2019-11-11T15:54:42.597 に答える
0

PHPのpassword_hash()関数は組み込み関数であり、さまざまなアルゴリズムとオプションで新しいパスワード ハッシュを作成するために使用されます。この関数は強力なハッシュ アルゴリズムを使用します。

この関数は 2 つの必須パラメータを取ります:$password$algorithm、および 1 つのオプション パラメータ$options

$strongPassword = password_hash( $password, $algorithm, $options );

現在許可されているアルゴリズムは次のpassword_hash()とおりです。

  • PASSWORD_DEFAULT
  • PASSWORD_BCRYPT
  • PASSWORD_ARGON2I
  • PASSWORD_ARGON2ID

例:

echo password_hash("abcDEF", PASSWORD_DEFAULT);

答え:

$2y$10$KwKceUaG84WInAif5ehdZOkE4kHPWTLp0ZK5a5OU2EbtdwQ9YIcGy

例:

echo password_hash("abcDEF", PASSWORD_BCRYPT);

答え:

$2y$10$SNly5bFzB/R6OVbBMq1bj.yiOZdsk6Mwgqi4BLR2sqdCvMyv/AyL2

BCRYPTのset オプションcost=12を使用するには、$options最初のパラメータ$passwordを のような強力なパスワードに変更します"wgt167yuWBGY@#1987__"

例:

echo password_hash("wgt167yuWBGY@#1987__", PASSWORD_BCRYPT, ['cost' => 12]);

答え:

$2y$12$TjSggXiFSidD63E.QP8PJOds2texJfsk/82VaNU8XRZ/niZhzkJ6S
于 2020-08-11T17:44:11.770 に答える