5

だから私はbcryptを試していました。私は3つの関数があるクラス(以下に示す、http://www.firedartstudios.com/articles/read/php-security-how-to-safely-store-your-passwordsから取得しました)を持っています。1 つ目はランダムなソルトを生成すること、2 つ目は最初に生成されたソルトを使用してハッシュを生成すること、最後は提供されたパスワードをハッシュ化されたパスワードと比較して検証することです。

<?php
/* Bcrypt Example */
class bcrypt {
    private $rounds;
    public function __construct($rounds = 12) {
        if(CRYPT_BLOWFISH != 1) {
            throw new Exception("Bcrypt is not supported on this server, please see the following to learn more: http://php.net/crypt");
        }
        $this->rounds = $rounds;
    }

    /* Gen Salt */
    public function genSalt() {
        /* openssl_random_pseudo_bytes(16) Fallback */
        $seed = '';
        for($i = 0; $i < 16; $i++) {
            $seed .= chr(mt_rand(0, 255));
        }
        /* GenSalt */
        $salt = substr(strtr(base64_encode($seed), '+', '.'), 0, 22);
        /* Return */
        return $salt;
    }

    /* Gen Hash */
    public function genHash($password) {
        /* Explain '$2y$' . $this->rounds . '$' */
            /* 2a selects bcrypt algorithm */
            /* $this->rounds is the workload factor */
        /* GenHash */
        $hash = crypt($password, '$2y$' . $this->rounds . '$' . $this->genSalt());
        /* Return */
        return $hash;
    }

    /* Verify Password */
    public function verify($password, $existingHash) {
        /* Hash new password with old hash */
        $hash = crypt($password, $existingHash);

        /* Do Hashs match? */
        if($hash === $existingHash) {
            return true;
        } else {
            return false;
        }
    }
}
/* Next the Usage */
/* Start Instance */
$bcrypt = new bcrypt(12);

/* Two create a Hash you do */
echo 'Bcrypt Password: ' . $bcrypt->genHash('password');

/* Two verify a hash you do */
$HashFromDB = $bcrypt->genHash('password'); /* This is an example you would draw the hash from your db */
echo 'Verify Password: ' . $bcrypt->verify('password', $HashFromDB);
?>

たとえば、「password」でハッシュを生成すると、ランダムに生成されたソルトを取得したハッシュ化されたパスワードが得られます。次に「password」をもう一度入力して検証機能を使用すると、パスワードが一致することを意味する true が得られます。間違ったパスワードを入力すると、false になります。私の質問は、これはどのように可能ですか? ランダムに生成されたソルトはどうですか?効果がないのはどうしてですか?

4

1 に答える 1

15

あなたが扱っている価値観をよく見てください。生成されるランダム ソルトは次のようになります。

abcdefg...

フィードされるものはcrypt次のようになります。

crypt($password, '$2y$10$abcdefg...')
                   |  |    |
                   |  |    +- the salt
                   |  +- the cost parameter
                   +- the algorithm type

結果は次のようになります。

$2y$10$abcdefg...123456789...
 |  |    |        |
 |  |    |        +- the password hash
 |  |    +- the salt
 |  +- the cost parameter
 +- the algorithm type

cryptつまり、結果のハッシュの最初の部分は、関数への元の入力と同じです。これには、アルゴリズムのタイプとパラメーター、ランダム ソルト、およびハッシュ結果が含まれます。

Input:  $password + $2y$10$abcdefg...
Output:             $2y$10$abcdefg...123456789...
                    ^^^^^^^^^^^^^^^^^
                   first part identical

パスワードを確認すると、同じ元のソルトが再び必要になります。同じソルトを使用した場合にのみ、同じパスワードが同じハッシュにハッシュされます。cryptそして、ハッシュが生成されたときと同じ操作を繰り返すためにそのまま渡すことができる形式で、ハッシュ内にまだ存在します。そのため、パスワードとハッシュの両方を検証関数に入力する必要があります。

crypt($passwordToCheck, '$2y$10$abcdefg...123456789...')

crypt最初に定義された文字数を含めabcdefg...て、残りを破棄します (そのため、salt は固定文字数である必要があります)。したがって、前と同じ操作と同じです。

crypt($passwordToCheck, '$2y$10$abcdefg...')

And は、同じ場合に限り 、同じハッシュを生成し$passwordToCheckます。

于 2013-05-24T13:33:55.093 に答える