パスワードベースのログインプロトコルを考え出すとき、多くのソリューションが頭に浮かびます:
4)が進むべき道だと思います。それは正しいですか、それとももっと良い方法がありますか?
PS:私が「ハッシュ」と書いた場合、それはsha256の100,000回の反復など、中程度に高価なハッシュ関数を意味します。
通信プロトコルは安全でなければなりません。通信チャネルが安全でない場合、認証は安全ではありません。 TLS/SSLは、通信プロトコルを保護する1つの方法です。 TLS/SSLを使用しない場合は、安全でないリンク上で安全な通信プロトコルを構築するためのフレームワークを構築する必要があります。適切に行われた場合(サーバーの認証、クライアントの認証、安全な鍵交換、暗号化、メッセージ認証、ダウングレードの堅牢な処理など)、プロトコルは複雑になります。すべての実用的な目的のために、TLS/SSLを再発明することになります。
したがって、記述されているように、#4と#5のみが安全であり、ほとんどのアプリケーションでは#4が主な選択です。これは、常に#4を使用する必要があると言っているわけではありませんが、このシナリオで#4が代替よりも劣っている理由を明確に説明できるはずです。
#5のバリアントは、ゼロの知識または否認性がコア設計要件であるニッチアプリケーションで役立ちます。理解すると複雑さが増すため、否認可能性が必要ない場合は、セキュリティを向上させることなく、より複雑なシステムを構築することになります。複雑さが高いほど、コストが高くなり、悪用可能な弱点が導入される可能性が高くなります。
ゼロ知識認証が役立つ例として、オンラインバックアップサービスがあります。サーバーが暗号化キーを持っている場合、サービスはそれらを明らかにするように強制できます(潜在的に秘密裏に、適切なプロセスなしで)。サーバーが暗号化キーを持っていない場合は、知らないことを明らかにするように強制することはできません。
生ファイルの暗号化は非常に簡単です。暗号化キーは、KDFを使用してユーザーのパスワードから生成されます。ファイルはクライアント側で暗号化され、サーバーに送信されます。サーバーはユーザーのパスワードや暗号化キーを決して持っていません。課題は、ユーザーを認証する方法です(アカウントのステータスの確認、請求、アップロードの許可など)。ユーザーがパスワードを送信するデフォルトのプロセス(#4)は、クライアント側のデータの暗号化を無効にします。そのため、サイトはユーザーにクライアント側でパスワードハッシュを取得させ、それをサーバーに提供させることができます。ハッシュは、暗号化キーとは異なる方法で作成する必要があります(kdfは同じですが、ラウンド数が異なるか、同じパスワードですが、静的プレフィックス)。レイアウトの改善点の1つは、サーバーがユーザーの認証ハッシュを直接保存する必要がないことです。サーバーはハッシュのハッシュを保存できます。これにより、パスワードリストが侵害された場合でも、誤った認証が防止されます。
リストされていないオプションは、クライアント側の証明書を使用してクライアントを認証することです。証明書の作成、管理、安全なストレージ/バックアップは完全にクライアント側で行う必要があります。そうしないと意味がありません。秘密鍵は、セキュリティを強化するためにクライアント側のパスワードで暗号化できます。 TLS/SSLはクライアント側の証明書をサポートしているため、これが設計要件である場合は、ホイールを再発明するのではなく、そこから始めます。 RSA上のECCの利点の1つは、スマートカードなどの低電力でメモリに制約のあるデバイスに適しているため、ユーザー教育は依然として課題ですが、これはより現実的なソリューションになります。