pwnedパスワードAPIを使用してユーザーのパスワードの選択を保護します.


時間ユーザーのほとんどは、彼らのパスワードがデータリークで妥協しているということを知りさえしません、そして、新しいサイトで登録している間、彼らはそれを使い続けます.
これは、あなたのユーザーアカウントに妥協を得ることができる非常に一般的な理由です.
それを保護するために、我々は登録の間、ユーザーパスワードリークをチェックするためにPwned Password APIを使うことができます.pwnedパスワードAPIはk-Anonymity modelを使用して、サーバーに実際のユーザーのパスワードを送信することなく、リークを確認します.

ハウツー

ステップ1
テストするパスワードのSHA - 1ハッシュを作成し、生成されたハッシュを2つの部分に分割します.最初の最初の5文字と残りの残りが含まれます.
const hash = sha1("admin@123") 
// 23D42F5F3F66498B2C8FF4C20B8C5AC826E47146

const prefix = hash.slice(0, 5)
// 23D42

const suffix = hash.slice(5)
// F5F3F66498B2C8FF4C20B8C5AC826E47146

ステップ2
今、我々はハッシュの最初の5文字でpwnedパスワードAPIを打つ必要があります.
Syntax:
GET https://api.pwnedpasswords.com/range/{first 5 hash chars}

Example:
GET https://api.pwnedpasswords.com/range/23D42
任意の一致がある場合、APIは、すべての一致する接頭辞の200を含む接尾辞で応答し、データセットに表示される回数をカウントします.
例:
F2304657BE5F09BF4C3B7437F5DDEE82E33:1
F2B1D579ED038F01B8D4D83361F9B00408A:2
F3422D62BF236E1E34035CCAED54E84EE8B:2
F3A46B097AB734EA1F28ED557413CEC03A5:3
F3F5E4A3788114EFBF26F4F7382864D6862:3
F4117F7EFB4ED0FE681051726EEA090E5AC:1
F43720FD73143B6E8A4A6B8C7E5A267AF32:1
F4E9AC75719EEE37231CE1A53CFF738C11B:2
F58377AC2990EAA2B6FEB595F973EE84ACD:1
F5BC40F7128B2A0A14D73781A000DD11959:2
F5C9F91934B26E4398080C1644003C546D6:9
F5D6D61A69CE393EE0B4B85E665162D5039:1
F5F1BB6CE22185813667B0EBE169A5EF7CD:12
F5F3F66498B2C8FF4C20B8C5AC826E47146:3423
F60C7D4EF1803230E8FD7E403047BCBAD55:1
F6117DEE59623D69DE06FCA2438F7BB8F85:2
F6601EF3EF8FDE535545A0FF350D4465D12:7
F6890FEC65093B4FF688C9812749F344673:3
F778202A2E4005DDF1127B277EFA268A8C2:1
...

ステップ3
これで、接尾辞の応答と検索を処理し、データセットで何回現れたかを確認できます.
パスワードadmin@123の場合には、接尾辞F5F3F66498B2C8FF4C20B8C5AC826E47146が3423回であることがわかります.
その後、アプリケーションのスタックに応じて別のパスワードを選択するユーザーを思い出させることができます.

チップ
Add Paddingを追加するのは常に良いでしょう.リクエストヘッダでは、サービスによって返されたハッシュサフィックスの数にかかわらず、800 - 1000の結果を返すことによって、さらにプライバシーを強化します.Read the full blog post on padding .

実装
上記の手順に従って手動で実装するか、パッケージを使用することもできます.
これはフロントエンドかバックエンドのどちらかである.
Latavelは、非常に人気のPHPフレームワークは、最近それをinbuildサポートを追加しました.

PHP (ラーラーベル)
Laravel 8.39では、上記のパスワードを使用することができます.
例:
<?php

$request->validate([
    'password' => [
        'required',
        'confirmed',
        Password::min(8)
            ->mixedCase()
            ->letters()
            ->numbers()
            ->symbols()
            ->uncompromised(), // Check for leaks
    ],
]);
フードの下でララベルはpwnedパスワードAPIを呼び出し、あなたのチェックを処理します.
ここでは、古いLALAVELバージョンで使用する場合に責任があるコードの一部です.
<?php

namespace Illuminate\Validation;

use Exception;
use Illuminate\Contracts\Validation\UncompromisedVerifier;
use Illuminate\Support\Str;

class NotPwnedVerifier implements UncompromisedVerifier
{
    /**
     * The HTTP factory instance.
     *
     * @var \Illuminate\Http\Client\Factory
     */
    protected $factory;

    /**
     * Create a new uncompromised verifier.
     *
     * @param  \Illuminate\Http\Client\Factory  $factory
     * @return void
     */
    public function __construct($factory)
    {
        $this->factory = $factory;
    }

    /**
     * Verify that the given data has not been compromised in public breaches.
     *
     * @param  array  $data
     * @return bool
     */
    public function verify($data)
    {
        $value = $data['value'];
        $threshold = $data['threshold'];

        if (empty($value = (string) $value)) {
            return false;
        }

        [$hash, $hashPrefix] = $this->getHash($value);

        return ! $this->search($hashPrefix)
            ->contains(function ($line) use ($hash, $hashPrefix, $threshold) {
                [$hashSuffix, $count] = explode(':', $line);

                return $hashPrefix.$hashSuffix == $hash && $count > $threshold;
            });
    }

    /**
     * Get the hash and its first 5 chars.
     *
     * @param  string  $value
     * @return array
     */
    protected function getHash($value)
    {
        $hash = strtoupper(sha1((string) $value));

        $hashPrefix = substr($hash, 0, 5);

        return [$hash, $hashPrefix];
    }

    /**
     * Search by the given hash prefix and returns all occurrences of leaked passwords.
     *
     * @param  string  $hashPrefix
     * @return \Illuminate\Support\Collection
     */
    protected function search($hashPrefix)
    {
        try {
            $response = $this->factory->withHeaders([
                'Add-Padding' => true,
            ])->get(
                'https://api.pwnedpasswords.com/range/'.$hashPrefix
            );
        } catch (Exception $e) {
            report($e);
        }

        $body = (isset($response) && $response->successful())
            ? $response->body()
            : '';

        return Str::of($body)->trim()->explode("\n")->filter(function ($line) {
            return Str::contains($line, ':');
        });
    }
}

ジャバスクリプト
JSでは、これはいずれかのフロントエンドやバックエンド(NodeJS)の要件ごとに実装することができますここでは、このタスクのためのよく維持されたライブラリです.
https://github.com/wKovacs64/hibp