私のパスワードはabc
だとしましょう。 HTTP経由でサーバーに送信します。
これをプレーンテキストで送信し、サーバーでハッシュしてデータベースのエントリと比較することもできますが、その接続でトラフィックを見ることができる人は誰でもパスワードをプレーンテキストで見ることができます。
それで、私はそれをクライアント側でハッシュし、サーバーにハッシュなしで比較させることができます(既にハッシュされているため、サーバーはハッシュを2倍にすることもできますが、この状況では違いはありません)。しかし、トラフィックを見ることができる人なら誰でも、ハッシュ化されたパスワードを見て、ハッシュ化されたパスワードをサーバーに送信すると、サーバーはそれを受け入れます。
HTTP経由でパスワードを送信するにはどうすればよいですか? RSA公開鍵暗号化などの暗号化アルゴリズムを実装する必要がありますか?それともこれは不可能ですか?
このメソッドは、どのブラウザでも使用できる必要があります。
TLSは実際にそれを行う唯一の方法です。
しかし、JavaScriptで暗号化するとどうなりますか?
攻撃者は、クライアントに送信するJavaScriptを変更したり、入力したすべての情報を記録する独自のJavaScriptを挿入したりすることができます。
次に、CSPとSRIを使用して、スクリプトの追加と自分のスクリプトの変更を防止します。
最新のツールを使用してサイトを保護していることをうれしく思いますが、SRIは 非セキュアコンテキスト の場合、実際には外部リソースの侵害からのみ保護します。攻撃者は、CSPヘッダーとSRIタグを単純に変更できます。
最初から暗号化を使わずにこれを行う方法は実際にはありません。それを行う唯一の標準的な方法は、TLSを使用することです。
HTTPSを使用する必要があることに同意しますが、実際の認証交換にソルトチャレンジレスポンス認証メカニズム(SCRAM、 RFC 5802 を参照)を使用することで、さらに安全にすることができます。
実装するのは簡単ではありませんが、その要点は、サーバーにパスワードを送信するのではなく、パスワードを知っているという証明をサーバーに送信することです。証明の導出はクライアントとサーバーからのナンスを使用するため、攻撃者が再利用できるものではありません(ハッシュ自体を送信するなど)。
これには、説明する基本認証でHTTPSを使用することに対するいくつかの追加の利点があります。
注意してくださいこれは、クライアントがSCRAM計算を実行できる場合にのみ安全ですなしサーバーからコードをダウンロードします。ファットクライアントを提供するか、ユーザーが自分で制御する独自のコードを記述できる場合があります。 HTTP経由でSCRAMコードをダウンロードすると、攻撃者はSCRAMコードを変更してパスワードをクリアテキストで送信したり、パスワードを公開したりすることができます。
この場合は必ずTLSをデプロイする必要があります。
HTTPを介してトランスポートセキュリティシステムを発明しようとする場合、最終的には、とにかくTLS機能のsusbsetを実装することになります。そのようなシステムを設計および実装する際に注意すべき多くの落とし穴があり、それらは多くの安全機能を提供しない言語でシステムを実装しようとする場合にさらに増幅されます。
JavaScriptで暗号化プロトコルの正しい実装を実装したとしても(すでに大きな課題です)、その実装がタイミング攻撃に耐性があることに依存することはできず、誰かがスクリプトを無効にすると(たとえば、NoScriptを使用して)すべてが壊れます)。
一般的なルールとして、セキュリティクリティカルなコードを最小限に記述する必要がある、最も単純でよく理解された信頼できるコンポーネントで構成される実装を選択する必要があります。 Andrew Tannenbaumを引用するには:
かなりの数の問題(アプリケーションのセキュリティで)は、バグのあるソフトウェアが原因で発生します。これは、ベンダーがプログラムにますます多くの機能を追加し続けるために発生します。
RSA公開鍵暗号化などの暗号化アルゴリズムを実装する必要がありますか?
あなたがそれを試してみることを考えているなら、あなたはまた、全力を尽くしてHTTPSを使用することもできます。あなたはエキスパートではないようですので、「独自のローリング」暗号化は間違いなくそれを安全でなくする誤実装があります。
それは実際にはかなり可能です。
パスワードはクライアント側でハッシュする必要がありますが、静的関数ではハッシュしないでください。次の方法は2つのステップを使用し、 ダイジェストアクセス認証 から着想を得ています。
注:サーバーは、Passwordと対応するKeyのHMACを保持します(ダイジェスト);
これにより、リプレイから保護されます。
私が目にする主な関心は盗聴に対する保護ではありませんが、プレーンテキストのパスワードがシステムログにさえサーバーに保存されないことを完全に確認するためです( Twitter または を参照)。 GitHub )。
注:HMACはPBKDF2で置き換えることができます。
安全でない接続を介してユーザーを認証する方法は実際にあります: Secure Remote Password(SRP)protocol 。 SRPは、中間者攻撃者がクライアントのパスワードを取得したり、認証を再生したりせずに、クライアントがサーバーに対して自分自身を認証できるように特別に設計されています。さらに、SRPによる認証が成功すると、クライアントとサーバーの両方が知っている共有秘密鍵が作成されますが、MitMは作成しません。この秘密鍵は、対称暗号化やHMACに使用できます。
ただし、SRPにはいくつかの制限があります。
言い換えると、SRPは、安全でない接続を介してコードをダウンロードする必要のない信頼できるクライアントがあり、ユーザーを登録する他の安全な方法がある場合にも役立ちますが、SRPは適していません。 Webアプリケーションの場合。 Webアプリは常にサーバーからコードをダウンロードするため、サーバーへの接続が安全でない場合、MitM(または他のネットワーク攻撃者、たとえばDNSのなりすまし)がWebアプリに悪意のあるコードを挿入する可能性があります。犠牲者はそれについてすることができます。そのコードが存在すると、入力したパスワードやその他のデータを取得し、生成されたキーを盗み、知らないうちに送信した要求や受信した応答を改ざんできます。
HTTPを使用して安全にパスワードを送信することは確かに可能です。そのための基準さえあります。それは呼ばれています HTTP-Digest
およびRFC 7616で定義されています。これは、しばらくの間、HTTP仕様の一部でした。もともとはMD5メッセージダイジェスト(「ハッシュ」)アルゴリズムのみを使用するように設計されていましたが、規格のその後の改訂では、クライアントとサーバーが使用するアルゴリズムをネゴシエートできるようになりました。
残念ながら、HTTPダイジェストには多くの問題があり、最も明白なのは、サーバーがパスワードを平文で持つ必要があることです。したがって、HTTPを使用してパスワードを安全に通信することは可能ですが、使用中にサーバーにパスワードを安全に格納することはできません。つまり、基本的に、それは役に立ちません。
他の人が言ったように、TLSは複数の問題を同時に解決し、かなり前方互換性があるため、TLSを実装する方が良いでしょう。
他の人がTLSを言ったように! TLS! TLS! (そしてまともなキーの長さも)
しかし、実装するためにHTTPとサーバーを使用する必要がある場合、これはプログラムによる使用ですか、それとも人間による使用ですか?人間が使用する場合、基本認証とフォームベースのどちらを使用していますか?そして、あなたの用途は少しロジックを適用することができますか? joe publicは使用できません。他に保護する必要があるものはありますか、それともパスワード自体だけですか?
もしそうなら、あなたは見ることができるかもしれません:
私はまだTLSを使用していますが、最近の証明書は安価(無料でも)なので、複雑な難読化スキームが存在する理由はまったくありません。