次の要件を持つセキュリティシステムを実装しようとしています。
- すべてのクライアントがパスワードを共有しますが、これはサーバーには認識されていません
- 各クライアントには、サーバーに認識されている一意のクライアントIDがあります
- パスワードを知っているすべてのクライアントは、サーバー上で同じ共有シークレットを生成できる必要があります(このシークレットは何でもかまいません。すべてのクライアントで同じであり、パスワード間で一意である必要があります)
- サーバーやトランスポートがハッキングされた場合でも、パスワードは安全に保つ必要があります
- 異なるclient-idを持つ別のパーティが、パスワードを知らずに同じサーバー側のシークレットを生成することは不可能でなければなりません。
これをグラフィカルに表現してみましょう。
Client Server
.--------------^-----------. .----------^----------.
f(client-id 1) g(client-id 1)
PASSWORD ----------------> request 1 ----------------> KEY
|| equal || equal
PASSWORD ----------------> request 2 ----------------> KEY
f(client-id 2) g(client-id 2)
ここで、f()[g()]は、クライアント[サーバー]がパスワード[リクエスト]に適用してリクエスト[キー]を取得する関数です。これらの関数は、client-idに依存する場合があります。
これを行う可能性のある2つのアプローチがありますが、必要なトラフィックとサーバーの負荷が少ない、よりシンプルなものを望んでいます。
「簡単」:クライアントはパスワードをハッシュします。クライアントとサーバーはそれぞれ、標準のメカニズム(SSLなど)を使用して接続を保護し、この接続を介してハッシュを送信します。
「もう少し賢い」:サーバーには固定秘密鍵がコード化されており、各クライアントには公開鍵がコード化されています。クライアントはパスワードをハッシュし、クライアントIDとXORし、公開鍵を使用してRSA/PGPで結果を暗号化します。次に、サーバーは秘密鍵を使用して要求を復号化し、結果をclient-idとXORして、パスワードハッシュに到達します。
どちらの場合も、サーバーはクライアントに対して同じシークレット、つまりパスワードハッシュを使用することになります。2番目のバージョンの利点は、残念ながらすべての場合にSSLに依存することができないため、本格的な鍵交換および暗号化システムのオーバーヘッドが不要なことです。実際、ハンドシェイクなしで1回のリクエストでサーバーシークレットを生成できます。2番目のバージョンのclient-id-XORは、リプレイ攻撃を防ぐために使用されます。別の方法では、異なるclient-idを持つサードパーティが同じ暗号化メッセージをサーバーに送信して、同じシークレットを生成する可能性があります。基本的に、それは塩を追加するためのオーバーヘッドのない方法です。
今の質問:
サーバー側のシークレットに関する要件は実際にはないので、クライアントがこのシークレットをローカルで生成できる場合でも、これを行うためのさらに簡単な方法があり、次のような任意精度の数値の高価なべき乗剰余を必要としません。 RSAはしますか?上記のf()とg()に対して、同じ結果を達成できる他のトラップドア関数を考えています。