# PHPパスワード生成・認証

**URL:** https://forum.ficusonline.com/t/topic/342
**Category:** WEB Design
**Created:** [2019 年 12 月 23 日午後 2:58 UTC](https://forum.ficusonline.com/t/topic/342 "2019-12-23T14:58:38Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![tk-fuse](https://forum.ficusonline.com/user_avatar/forum.ficusonline.com/tk-fuse/32/255_2.png) [@tk-fuse](https://forum.ficusonline.com/u/tk-fuse)
#### Post date: [2019 年 12 月 23 日午後 2:58 UTC](https://forum.ficusonline.com/t/topic/342/1 "2019-12-23T14:58:38Z")

</div>

### PHPによるパスワードの生成と認証(CRYPT\_BLOWFISH)

UserFrostingではパスワードの生成にpassword\_hash関数(CRYPT\_BLOWFISH)を採用しています。  
このログインシステムとアプリ(FlexisipはMD5関数使用)のパスワード認証システムの整合性を図るため、PHPによるログインシステムのパスワード生成・認証方法について纏めます（UserFrostingまたはFlexisipのどちらかの認証方法を採用）。

> **[UserFrosting Documentation | User Accounts](https://learn.userfrosting.com/users/user-accounts#password)**
>
> UserFrosting ships with everything you need to create user accounts, and a rich set of features for users and administrators.

以下コマンドによりターミナルでPHPコードを実行します。

`$ php -a`

### password\_hash関数

> **[PHP: password\_hash - Manual](https://www.php.net/manual/en/function.password-hash.php)**
>
> Creates a password hash

> password\_hash ( string `$password` , int `$algo` [, array `$options`] ) : string

以下 **int `$algo`** に該当する箇所に適用する **定義済み定数** です。

> **[PHP: Predefined Constants - Manual](https://www.php.net/manual/en/password.constants.php)**
>
> Predefined Constants

- PASSWORD\_DEFAULT
- PASSWORD\_BCRYPT - Use the CRYPT\_BLOWFISH algorithm to create the hash. This will produce a standard crypt() compatible hash using the “$2y$” identifier. The result will always be a 60 character string, or FALSE on failure.
- PASSWORD\_ARGON2I
- PASSWORD\_ARGON2ID

**ex)**

```auto
php > $options=['cost' => 04];
php > echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options);
$2y$04$x3kiESnKtbj6/FdxUQzEE.vUhNdZP/124VsHrNU99dtxM3rXSKlFO

```

PASSWORD\_BCRYPT(CRYPT\_BLOWFISH)の詳細についてはPHPの **crypt関数** を参照のこと。

> **[PHP: crypt - Manual](https://www.php.net/manual/en/function.crypt.php)**
>
> One-way string hashing

上記60文字のハッシュ出力は、

1. **$2y$:ハッシュアルゴリズム(CRYPT\_BLOWFISH)**
2. **04$:ハッシュ回数（2^04=16回)**
3. **x3kiESnKtbj6/FdxUQzEE.:ソルトsaltと呼ばれる22文字のランダムな文字列（自動生成）**

を含んだ形で出力されます。

パスワードが同じでも生成されるハッシュ出力は異なります。同じコマンドを実行します。

```auto
php > echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options);
$2y$04$6XJn2jDzu/iWxOXobKGMPuxK77wCbSIyJDo1QPlQruqq9E5j.oaq6

```

パスワードとして保存される上記ハッシュ出力を、その都度変化させることでセキュリティを確保しています。パスワード認証の際には、次の **password\_verify関数** により、 **上記項目1~3を含んだ60文字のハッシュ出力** と**平文のパスワード(“rasmuslerdorf”)** をセットで指定することで正誤を判定します。

### password\_verify関数

> **[PHP: password\_verify - Manual](https://www.php.net/manual/en/function.password-verify.php)**
>
> Verifies that a password matches a hash

正しい場合は1を出力します。

> password\_verify ( string $password , string $hash ) : bool

**ex)**

```auto
php > $hash='$2y$04$x3kiESnKtbj6/FdxUQzEE.vUhNdZP/124VsHrNU99dtxM3rXSKlFO';
php > echo password_verify('rasmuslerdorf', $hash);
1

php > $hash='$2y$04$6XJn2jDzu/iWxOXobKGMPuxK77wCbSIyJDo1QPlQruqq9E5j.oaq6';
php > echo password_verify('rasmuslerdorf', $hash);
1

```

---

<div class="post-metadata">

### Author: ![tk-fuse](https://forum.ficusonline.com/user_avatar/forum.ficusonline.com/tk-fuse/32/255_2.png) [@tk-fuse](https://forum.ficusonline.com/u/tk-fuse)
#### Post date: [2019 年 12 月 25 日午前 7:15 UTC](https://forum.ficusonline.com/t/topic/342/2 "2019-12-25T07:15:14Z")

</div>

**パスワードハッシュに何故ソルト:Saltが必要か？**

> **[Why do you need to Salt and Hash passwords? | Culttt](https://culttt.com/2013/01/21/why-do-you-need-to-salt-and-hash-passwords/)**
>
> This article explains the importance of securely storing user passwords by using a hashing algorithm like PBKDF2 and salting.

平文パスワードにランダムな文字列であるSaltを混合させて複数回ハッシュすることで、この文字列が盗まれた場合でも、その解読には莫大なコンピュータリソースが必要となるため。  
パスワード解読の困難度をより高くする為に必要なオプションです。

---

<div class="post-metadata">

### Author: ![tk-fuse](https://forum.ficusonline.com/user_avatar/forum.ficusonline.com/tk-fuse/32/255_2.png) [@tk-fuse](https://forum.ficusonline.com/u/tk-fuse)
#### Post date: [2019 年 12 月 27 日午後 12:46 UTC](https://forum.ficusonline.com/t/topic/342/3 "2019-12-27T12:46:01Z")

</div>

### Laravel Hashing

> **[Hashing | Laravel 12.x - The clean stack for Artisans and agents](https://laravel.com/docs/7.x/hashing)**
>
> Laravel is a PHP web application framework with expressive, elegant syntax. We’ve already laid the foundation — freeing you to create without sweating the small things.

上記 **Laravel** による **Hash** ファサードにより、パスワードアルゴリズムを[Bcrypt](https://en.wikipedia.org/wiki/Bcrypt)または[Argon2](https://en.wikipedia.org/wiki/Argon2)から選択します。各アルゴリズムの細かい設定は **config/hash.php** 内で定義します。  
上記アルゴリズム以外を利用する場合には、PHPのハッシュ関数を適用します。

**UserFrosting** はPHPフレームワークである **Laravel** により構築されていて、パスワード生成・認証にはFacadeクラスを利用しています。以下Password.phpでPasswordクラス内にhash関数は存在しないのですが、その場合、Facadeクラスの\_\_callStatic():を通してHasherクラスのhash関数が呼び出されます。クラスからインスタンスを生成し処理する手間を省いているようです。

### Laravel Facades

[https://medium.com/a-young-devoloper/understanding-laravel-facades-4802025899e6](https://medium.com/a-young-devoloper/understanding-laravel-facades-4802025899e6)

> <https://stackoverflow.com/questions/19840911/callstatic-instantiating-objects-from-static-context>

### Registration.php

```auto
...php
protected function hashPassword()
    {
        $this->userdata['password'] = Password::hash($this->userdata['password']);
    }
...

```

### Password.php

```php
...

use UserFrosting\System\Facade;

class Password extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'passwordHasher';
    }
}

```

### Facade.php

```php
/**
     * Handle dynamic, static calls to the object.
     *
     * @param string $method
     * @param array $args
     *
     * @throws \RuntimeException
     *
     * @return mixed
     */
    public static function __callStatic($method, $args)
    {
        $instance = static::getFacadeRoot();

        if (!$instance) {
            throw new RuntimeException('A facade root has not been set.');
        }

        switch (count($args)) {
            case 0:
                return $instance->$method();
            case 1:
                return $instance->$method($args[0]);
            case 2:
                return $instance->$method($args[0], $args[1]);
            case 3:
                return $instance->$method($args[0], $args[1], $args[2]);
            case 4:
                return $instance->$method($args[0], $args[1], $args[2], $args[3]);
            default:
                return call_user_func_array([$instance, $method], $args);
        }
    }

```

### Hasher.php

```php
/**
     * Hashes a plaintext password using bcrypt.
     *
     * @param string $password the plaintext password.
     * @param array $options
     *
     * @throws HashFailedException
     *
     * @return string the hashed password.
     */
    public function hash($password, array $options = [])
    {
        $hash = password_hash($password, PASSWORD_BCRYPT, [
            'cost' => $this->cost($options),
        ]);

        if (!$hash) {
            throw new HashFailedException();
        }

        return $hash;
    }

```

---

<div class="post-metadata">

### Author: ![tk-fuse](https://forum.ficusonline.com/user_avatar/forum.ficusonline.com/tk-fuse/32/255_2.png) [@tk-fuse](https://forum.ficusonline.com/u/tk-fuse)
#### Post date: [2020 年 2 月 1 日午前 1:57 UTC](https://forum.ficusonline.com/t/topic/342/4 "2020-02-01T01:57:47Z")

</div>

### hash関数

> **[PHP: hash - Manual](https://www.php.net/manual/en/function.hash.php)**
>
> Generate a hash value (message digest)

phpによるテキストデータのハッシュ出力の確認

```auto
$ php -a
php > echo 'MD5: ' . hash('md5', 'yourpassword') . "\n";
MD5: 637b9adadf7acce5c70e5d327a725b13
php > echo 'SHA-256: ' . hash('sha256', 'yourpassword') . "\n";
SHA-256: e3c652f0ba0b4801205814f8b6bc49672c4c74e25b497770bb89b22cdeb4e951

```
