現在、シンプルなログインシステムを実装しています。すべてのユーザーパスワードをデータベースに安全に保存したい。パスワードは最も重要なコンポーネントです。他のすべてのユーザーデータは重要ではありません。アカウントがハッキングされた場合、パスワードがその罰金を理解できない限り。その他のデータには、スコアやアカウント作成日などがあります。
一部のユーザーが他のサイトと同じパスワードを使用することを想定しています。そのため、潜在的なハッカーがパスワードを読み取れないようにする必要があります。
ハッカーが実際のパスワードを見ることを防ぐために、クライアント側でハッシュを何らかの方法で生成できますか?
あなたが言う前に、私はクライアントでそれをするべきではありません。サーバーには実行が必要な一定のゲームループがあり、誰かがアカウントを登録したり、ログインしようとしたりするたびにゲームが遅れることはありません。このアプローチでは、サーバーの負荷の一部が軽減されます。
編集:この質問はクローズされたので、詳しく説明したいと思います。クライアントに移動すると、パスワードをハッシュするときに、より多くのラウンドを使用できるようになります。これは、サーバーや他のユーザーのエクスペリエンスに何らかの影響を与えないためです。これにより、ユーザーがリクエストをスパム送信したりサーバーの速度を低下させたりすることを防ぐのもはるかに簡単になります。
一部のユーザーが他のサイトと同じパスワードを使用することを想定しています。
他のサイト(自分のサイト以外)でのパスワードの使用を保護するコンテキストでは、は問題ではありませんパスワードをハッシュするかどうかクライアント側またはサーバー側。
ただし、クライアント環境(つまり、Webブラウザー)によっては、十分な検索が難しい場合があります十分最適化された(強い)スローパスワードハッシュの実装。 (例:Argon2またはBCrypt)したがって、クライアント側のハッシュの提案は、ネイティブ暗号化が利用可能なアプリ環境でのみ実用的である可能性があります。
もちろん、クライアント側のハッシュは、パスワードがyour siteで使用されるのを防ぐためには何もしません。ハッシュを盗んだ攻撃者は、クライアント側のハッシュルーチンをスキップして、サーバーで認証を受けることができます。 (クライアントを信頼しないでください)幸い、この攻撃ベクトルはサーバー側で解決できます。 (下記参照)
サーバーには実行が必要な一定のゲームループがあり、誰かがアカウントを登録したり、ログインしようとしたりするたびにゲームが遅れることはありません。このアプローチでは、サーバーの負荷の一部が軽減されます。
ご存知のように、従来はサーバー側をハッシュすることが推奨されています。負荷が気になる場合は、いくつかの提案を送信します。
Work Factorは、ターゲットハードウェアで約100ミリ秒かかるように調整する必要があります。 (あなたのサーバー)それで、それは実際にはそれほどラグではありませんね?私は通常50ミリ秒から500ミリ秒を推奨していますが、あなたのサイトはより低い値を使用しても、依然として堅牢であると考えられます。
ハッシュは、メインのゲームループ(非同期)から個別のスレッドにある必要があります。ハッシュは計算中です。
サーバーが計算するハッシュの量を制限するために、何らかの形式のDoS保護を含める必要があります。通常、サイトはサインインの試行を(ユーザーごとに)抑制し、攻撃者がブルートフォースを効果的に実行できないようにします。そのようなスロットルは、無限のハッシュ計算を妨げます。
必要に応じて、パスワードをbothクライアントandサーバーでハッシュできます- ifクライアント環境には十分なネイティブサポートがあります。 (上記の説明)次に、サーバー側の作業係数をさらに小さくすることができます。
クライアント側に十分に強い作業係数がある場合、実際にはサーバー側で迅速な(つまりゼロラグの)SHA-2のみを実行することが合理的になり、問題が完全に解決されます。 ( thanks @HenningMakholm )
最後に、クライアントがパスワード(またはハッシュ)をHTTPSのみで送信することを確認します。想定されるハッシュの量がHTTPサイトに入力されたパスワードを保護しないため、これは最も重要なことです。
目的がonlyであり、データベースが危険にさらされたときにユーザーをパスワードの再利用から保護する場合、はい、ハッシュをクライアント側に移動できます。
アプリケーションを実際に保護するには、これでは一般的に不十分であることを受け入れる必要があります。一般に、そのようなアプローチのほとんどには次の2つの障害のいずれかがあるため、不十分です。
彼らは「パスワードのような」トークンを送信します。つまり、doがHTTPSなどに関するあなたの仮定を破った場合、私はあなたとしてログインすることができます。
彼らは「パスワードのような」トークンを保存します。つまり、doがusersテーブルの行を確認すると、そのユーザーとしてログインできるという意味です。
1つ目は、「サーバーに送信し、サーバーがそれをハッシュし、サーバーがハッシュがデータベース内の何かと等しいかどうかを比較する」で終わるクライアント側の操作です。 2つ目はチャレンジ/レスポンス方式の特徴です。「この文字列を送信し、キーで暗号化し、暗号化されたバージョンを返信します。暗号化を解除して元のチャレンジを再度取得できるかどうか確認します。
システムがasymmetric crypto、公開鍵に基づいている場合、実際にはcanこれら2つを回避することが明らかになるので、私は2番目のケースの単語を非常に慎重に選択しましたと秘密鍵。クライアントが秘密鍵を計算できる場合、サーバーは公開鍵を保存できます。これは、RSAなどでは完全に実行不可能でした(「ああ、私はパスワードを決定論的な乱数ジェネレータのシードとして使用し、毎回キーを設定します」-冗談ですか?)楕円曲線暗号。秘密鍵は、文字通り特定の長さの任意のビット文字列であることがよくあります。キーを取得する関数を使用してそれを取得すれば、安全です。
ただし、どのような場合でも「独自の暗号化」を行いたくない場合があります。その場合は、スタンフォードで作成されたSecure Remote Password(SRP)プロトコルの実装を探します。多くの暗号解読が行われており、しばらくの間使用されており、おそらく見つけて使用できる実装があります。
クライアント側でパスワードハッシュの高価な部分を実行できますが、注意が必要です。たとえば、次のプロトコルは間違っています:
username
をサーバーに送信します(username, salt, hashed_pwd)
_salt
をクライアントに送信します。client_hash = pwhash(salt, pwd)
client_hash
_をサーバーに送信します。client_hash
_を_hashed_pwd
_と比較します。それらが等しい場合、ユーザーは認証されます。そのプロトコルは安全ではありませんサーバーが格納するハッシュは「パスワードと同等」であるため、サーバーのパスワードデータベースを盗んだハッカーは、プロトコルを介してハッシュを再生し、ユーザーになりすますことができます。したがって、サーバーstillはソルトハッシュを実行する必要があります;それができることは、サーバーが高速ソルトハッシュを計算するだけでよいように、最もコストのかかる計算をクライアントに移動することです。
より良いプロトコルはこれです:
username
をサーバーに送信します(username, client_salt, server_salt, hashed_pwd)
_を検索します。 (これは変更されたステップ悪いプロトコルと比較して:良いプロトコルには2つのソルトがあり、1つはクライアントが使用します、サーバー用に1つ)client_salt
_をクライアントに送信します。client_hash = pwhash(client_salt, pwd)
client_hash
_をサーバーに送信します。server_hash = fast_salted_hash(server_salt, client_hash)
を計算します。 _fast_salted_hash
_関数は、HMACまたはBlake2で、_server_salt
_をキーとして使用できます。 (これは、不正なプロトコルには存在しなかった追加の手順です。)server_hash
_を_hashed_pwd
_と比較します。それらが等しい場合、ユーザーは認証されます。クライアント側でパスワードハッシュをソルト化することで、同じパスワードを選択したユーザーがネットワーク上で異なるハッシュを送信することになるため、1つのクライアントを侵害してその_client_hash
_を知るハッカーは、それを再生してログインできなくなります。同じパスワードを持つユーザー。
_client_hash
_のソルトハッシュのみを保存することにより、従来のパスワードハッシュと同様に、パスワードデータベースを盗む攻撃者から身を守ります。