web-dev-qa-db-ja.com

2つのクライアント間の接続を暗号化する安全な方法で、パッシブとアクティブの両方の敵から保護

最近、暗号化とその背後にある方法に興味を持ちました。だから楽しい/学校プロジェクトのために、私は2つのクライアント(チャットとファイル)の間でデータを暗号化するためにpython)でプログラムを構築しています。

パッシブ攻撃とアクティブ攻撃の両方に対して本当に安全にする方法を本当に知りません。今の私の考えは、サーバーを使用して、次の方法でクライアント間のハンドシェイクを確立することです。

  1. クライアントが起動すると、クライアントはサーバーに接続して、クライアントが生存していることを知らせます。
  2. クライアントbobはサーバーに、クライアントAliceに接続したいことを知らせます
  3. サーバーがクライアントのアリスにメッセージを送信し、ボブは安全な接続を確立したい
  4. アリスは接続を受け入れることをサーバーに伝えます
  5. サーバーは乱数を生成し、クライアントの公開鍵を使用してそれを暗号化しますクライアントは秘密のRSA鍵がハードコードされています(接続/クライアントごとに変更されません)
  6. サーバーは乱数をアリスとボブの両方に送信します
  7. アリスとボブは、乱数を復号化してハッシュし、どちらもサーバーに送信します
  8. サーバーは両方のハッシュが同じかどうかをチェックします(どのハッシュも調整されていません)
  9. サーバーがOKまたはエラーを両方の当事者に送信します
  10. Aliceとbobは、乱数と同じ回数だけ数値をハッシュします(したがって、サーバーが1234を送信した場合、1234回ハッシュします。
  11. アリスとボブは、Diffie-Hellman鍵交換を使用してこの接続の共通鍵をセットアップし、AESとの交換を暗号化します。
  12. 共通鍵が決定したら、この鍵またはこの鍵のハッシュをAES暗号化に使用します(この鍵は接続ごとに変更され、すべてのデータはこのチャネルを介して送信されます)

攻撃者がコードをリバースエンジニアリングして秘密キーを取得し、サーバーが侵害された場合にAliceとBobの両方の接続でアクティブな攻撃を使用できる場合にこのプロトコルで発生する唯一の問題はORです。

Py2exeを使用してコードをコンパイルするので、キーを取得するのは困難ですが、どれだけ難しいかはわかりません。

長い質問で申し訳ありませんが、キーをクライアントにハードコードするのは本当に恐ろしい考えのように思えますが、ここからどこに行くべきかわかりません。

このアイデアについての考え/改善点/どうすればもっと上手くできるでしょうか?

誤字があって申し訳ありません。英語は私の第一言語ではありません。

4
Alfuananzo

配布されるソフトウェアに秘密鍵をハードコードすることはできません。

私が見る2つのオプションは次のとおりです。

  1. 各クライアントに、サーバーとの通信に使用する固有の鍵ペアを生成させます。ボブは、最初に接続するときに、公開鍵をサーバーに送信します。次に、サーバーはボブへのメッセージを彼の公開鍵で暗号化します。サーバーとアリスの間の最初の通信は、将来の通信に使用できるように、アリスに公開鍵を要求するサーバーになります。サーバーは、公開鍵で暗号化された対称鍵をBobとAliceのそれぞれに渡し、将来の通信に使用できます。
  2. サーバーにキーペアを与えます。ボブは最初にサーバーに接続するときに、サーバーの公開鍵で暗号化する対称鍵を作成します。サーバーとボブはこれを使用して、以降の通信を暗号化します。サーバーが最初にアリスに連絡するとき、それは彼女にその公開鍵を渡します。アリスは、対称鍵を作成してサーバーに送信し、サーバーの公開鍵で暗号化して応答します。サーバーは、このキーを使用してアリスと通信できます。

上記のオプション1では、クライアントが各サーバーに一意のキーペアを生成するSSHモデルと呼ばれるものを使用します。オプション2では、サーバーが鍵ペアを持っているSSLモデルと呼ばれるものを使用します(ただし、SSLは署名付き証明書で公開鍵を通信します)。

上記を実行すると、非常に優れたセキュリティが得られます。とは言っても、完璧ではありません。問題は、 MiTM攻撃 に対して依然として脆弱であることです。

安全に機能するために、SSHでは、サーバーに初めて接続するときにサーバーの公開鍵のフィンガープリントを検証する必要があります。プロトコルは、これを検証する方法を説明していません。ほとんどのユーザーは検証せずに「OK」と言うだけですが、そこにはMITMの可能性があります。

SSLは、証明書チェーンを検証することにより、サーバーからの公開鍵を自動的に検証します。これは、OS、ブラウザ、またはその他のクライアントにプレインストールされた信頼されたルート証明書を持つキーストアがあるためにのみ機能します。その検証がないと、サーバーの証明書の公開鍵が検出されずに偽造される可能性があります。

既存のセキュリティインフラストラクチャを使用しない限り、これまで以上にうまくできるとは思いません。たとえば、サーバーでSSLを実行し、SSLハンドシェイクで渡された証明書をクライアントに検証させることができます。

クライアントがサーバーの公開鍵を適切に検証しない場合はSSHと同じくらい安全になるので、私はこれを問題とは考えていません。 IMO、それはかなり良いことです。

これはとてもクールな問題です。楽しい!

PS:あなたの英語について謝罪する必要はありません。ネイティブスピーカーと同じくらいいいです。

1
Neil Smithline

質問の基本は、エンドポイントがセキュリティで保護されていない場合、キー、それらが取得できるものは何でもかまいません。そのため、エンドポイントのセキュリティで保護されたトランザクションの場合、端末自体は所有者のイージスの下にあります。 ATM、キャッシュポイントなど.

0
munchkin

素晴らしいプロジェクトですが、いつものように、実際に車輪を再発明すべきではありません。プロダクションで使用するためにそのようなプロトコルを作成することは、ほとんどすべての場合において悪い考えです。 Bruce SchneierのCryptography Engineeringの本を読むことをお勧めします。それは簡単な読み物ではありませんが、間違いなくすべての質問をクリアします。まず第一に、実行可能ファイルにキーを書き込むのはひどい考えだと思います。これは、メソッドではなく、機密データを保護するキーでなければなりません(ケルクホフの原理を参照)。また、キー管理をPITAにします。サーバーをキーネゴシエーションに関与させるのはなぜですか?私が間違っていない場合は、ピア認証にその「1234」キーを使用します。クライアントが署名するだけで、クライアントキーを使用してサーバー側で検証できます。 「共通鍵が決まったら、この鍵またはこの鍵のハッシュを使う」と書いた。繰り返しになりますが、キーの強さは、メソッドではなくセキュリティを提供する必要があります。メソッドは再現できますが、キーは再現できません。

全体として、独自のプロトコルを発明するのではなく、よく知られているプロトコルを使用する必要があると思います。暗号化プロトコルを学ぶだけのプロジェクトであれば、他の実用的なプロトコルを調べることをお勧めします。

0
djozsef

どこにいるかにもよるが、これは素晴らしい高校のプロジェクトだと思う。 ipsec + dnssec + pki + tls/sslルートは、この演習の非常にプロトコルベースのファセットです。物事の物理的なセキュリティの側面も取り上げたいと思うかもしれません。たとえば、緩和要因としてエンドポイントの場所を提示します。結局のところ、機器用のFIPレベルのスキフは何もありません。

0
mincewind