web-dev-qa-db-ja.com

クライアントとサーバー間の通信チャネルを適切に暗号化する方法(SSLなし)?

私は暗号化の世界に乏しい知識を持っています、私はそれを学び始めたばかりなので初心者です:)

暗号化の分野に参入するためのプロジェクトとして、安全な方法でデータを送受信できるclient\serverプログラムを記述したい(ie暗号化)。

クライアントとサーバー間、または2つのクライアント間のトラフィックを暗号化するとします。私が実行しているサービスは、既知のポートでのみサーバーまたは別のクライアント(サーバーとしても機能します)と通信できます。サーバーは基本的に、デフォルトポートの一方の側で接続をリッスンします。

ネットワーク上でリッスンしている第三者が会話の内容を解読したり、サービスを偽装したりする可能性がないように、これらのサービスが互いに対話できるようにしたいと考えています。

私はキーを交換する新しい方法を探していません(または私がすべきですか?)、キーをサービスに安全に保存することができるので、xメッセージをyに送信し、返信すると、コンテンツと応答を​​復号化できるのはそれらだけになります(もちろん、(verifiedservice)。

  • 補足:キーはプログラムに保存できます-ハードコードするか、クライアントに渡すことができるもの(IP、コンピューター名、ユーザー名、その他の定数の組み合わせなど)の組み合わせから生成できます。キーを生成できるようになります(IP、コンピューター名、ランダムシードを渡すとします。これらの値からキーを作成するための既知の式があります)。

暗号化には対称キーを使用する必要がありますが、SSLの場合と同様に、事前に生成された2つのキーを使用することもできます。

同じキーを何度も使用している場合、サードパーティがトラフィックを傍受してキーを取得できることを知っています(数学が最適ですが、どのように行われますか)。彼が収集するデータが多いほど、簡単に取得できます。 (?).

では、誰も暗号化キーを取得できない(最終的にはデータを読み取る)ことを約束するにはどうすればよいですか?どの暗号を使用する必要がありますか?旅を始める前に知っておくべきことは何ですか?

6
YSY

これは実際に他の人が示唆したよりも簡単です。これが私が提案するものです:

  1. RSAを使用して公開鍵と秘密鍵のペアを生成します。これは、opensslを使用して任意のUNIXマシンで実行できます:openssl genrsa -out rsa.private 2048
  2. クライアントでハードコーディングされた公開鍵を配布します。
  3. クライアントがログインすると、クライアントは秘密の共有キーを生成し(opensslまたは他のよく知られた暗号化ライブラリも使用)、公開キーを使用してそれを暗号化します。
  4. クライアントとサーバー間のすべてのデータは、セッションの間、新しい共有キーで暗号化する必要があります。

キーを再生成する前のセゾンの長さを1時間または数時間に制限する、サーバーにメッセージダイジェストに署名させるなど、他にも多くのことができます。暗号化を完全に理解することで、それらがその理由ですが、基本的な実装(中から低値のデータ)にはこれで十分です。

8
Charlie B

コーディングする前に、これを読んでください: http://www.schneier.com/book-applied.html

この質問は広すぎるため、残念ながらStackExchangeには当てはまりません。暗号化の長さと幅は、数学、コンピューターサイエンス、および工学の小学校での正式な教育なしに、ある程度の成功を収めて1人の個人がめったに横断することはめったにありません。

この本は、一般的な概念、一般的な間違い、学ぶべき遠征、および従うべき例を学ぶのに役立ちます。

2
MToecker

基本的に、SSLが提供する種類のトンネルが必要です。これらのことを正しく行うのは実際には困難です。

SSLはいくつかのものの集まりです。トンネル自体があります。共有シークレット( TLS仕様 で「プレマスターシークレット」と呼ばれるもの)があり、クライアントとサーバーが使用するアルゴリズムについて合意すると、個別仕様のセクション6で説明されているように、データレコードは暗号化できます。そのポイントに到達するために、SSLは最初にhandshakeを実行し、そこで非対称暗号化が行われます。クライアントとサーバーの両方を制御していて、それらがすでに「本質的に」秘密を共有している場合は、ハンドシェイクをスキップできます。

ハンドシェイク中に、サーバーは不透明なブロブ(「証明書」)を送信し、クライアントはこれを使用してサーバーの公開鍵を取得できます。クライアントがサーバーの公開鍵について固有の知識を持っている場合は、サーバーが送信したものを完全に無視して、既知の公開鍵を使用することができます。証明書の検証(かなり複雑なコード)は、クライアントがサーバーの公開キーを動的に検出したい場合にのみ使用されます-これは、ウェブ。ただし、シナリオによっては、これは必ずしも必要ではありません。

現在、このサイトで SSLの仕組み についての質問があり、非常にわかりやすい回答(長い場合)が示されています。

SSLで刺激を受けない場合は、SSHを参照してください。同じ概念、異なるプロトコル。 SSHはいくつかのドキュメントで説明されています。 RFC 4251 で始まります。

1
Thomas Pornin

私はこれが古い投稿であることを理解しています。うまくいけば、トピックから離れすぎずに、少し考えてみます。

まず、キーを事前に設定するという点では、これは悪い習慣です(特に、DESのような古い暗号化アルゴリズムを使用している場合は、キーを復元するのがかなり簡単です)。キーを永続的に使用するだけでなく、定期的にキーをローテーションできるようにする;原則として、少なくともキーを長く使用するほど、安全性が低下します(誰かが何らかの方法でキーを手に入れようとした場合、使用したすべての通信を解読できるためです)そのキー)。

実際には、適切に適用された最新の暗号化アルゴリズムは解読するのが非常に難しく、一般に既知のプレーンテキストおよび選択されたプレーンテキストの攻撃に対してかなり耐性がありますが、ハッキングなどのキーを取得したり、アクセス-サーバーまたはクライアントコンピューター;これは実際に最近多くの企業で起こっています(最も悪名高いのはTarget)。これは、プレーンテキストでサーバーに保存する場合に特に問題になります。 (このようなものを適切に保存する方法についてのドキュメントはたくさんあります。私はこれをキーで試したことはありませんが、パスワードを保護する方法と同様の手順を実行したいと思います)。

クライアントとサーバーの両方への物理的なアクセスが継続している場合、キーローテーションの問題は問題になりません。その場合、手動で定期的にキーを更新できます(忘れない限り)。 (誰かがサーバーまたはクライアントをハッキングしたり、物理的にアクセスしたりした場合に備えて、クライアントとサーバーの両方に安全に保存する必要があります)。

原則として、セキュリティは常に相対的であることを忘れないでください。そのため、セキュリティを確保したい場合、質問は常に「どの程度安全ですか」です。たとえば、特定のデータベース値を暗号化するためにアフィン暗号を使用していたプロジェクトがありました。これらは簡単に解読できますが、私たちの目的は、意図的な悪意ではなく、偶然の観察者によるアクセスを防ぐことでしたので、十分でした。実際には、このような古いアルゴリズムのほとんどはすでにひどく壊れているため、十分なリソースを備えた十分に動機付けられた攻撃者に対する保護はほとんどありません。たとえば、DES(データ暗号化標準)は、キーが短すぎるため "ブルートフォース"攻撃に対して脆弱です(90年代後半でも、ブルートフォースでキーをブルートフォースすることが可能でした24時間)ですが、やる気のない攻撃者に対して少なくともある程度の保護を提供します。

また、これはおそらく元の投稿で意図したものとは正確には一致しませんが、攻撃者がメッセージを復号化しないことを文字通り不可能にする実用的なアルゴリズムはありません。 AESのような最新のアルゴリズムでは、今のところ実用的ではありません(ただし、原則として不可能ではありません)。 (キーフレーズ:「今のところ。」DESは最初に開発されたときは安全でしたが、20年後に公にクラックされ、政府がそれ以前にそうすることができた可能性があります)。ワンタイムパッド(一度だけ使用するメッセージと同じ長さの完全にランダムなキーがある場合)など、「完全なセキュリティ」を備えたアルゴリズムがあります。これらのアルゴリズムについては、これ以上の発見は不可能です。ただし、このアルゴリズムは、鍵交換の問題があるため実用的ではありません。鍵を安全に交換することは、メッセージを安全に交換することと同じくらい困難です。

私は過去に同様の状況に直面し、GETとPOST HTTPS経由のリクエストを使用して解決しました。Androidでは、コーディングがかなり簡単で、含まれているHTTPクライアントがあなたのためにすべての暗号のものを世話するので、簡単な解決策を持ち、危険な「独自の暗号を作る」ことを避けることができます

0
Caterpillaraoz

SSL/TLSなしで安全なチャネルを作成したい場合は、SSL/TLSを少しずつ再実装する必要があります。除外しても安全な接続を残しておくことができるものはほとんどありません-そこにあるすべてのものは、約20年の使用とレビューと分析の結果です。

これは、独自の暗号化を導入するべきではないと常に耳にする理由のかなり重要な部分です。そのため、ゼロから始めて独自の道を作るのではなく、仕様を理解し、既存の実装がどのように機能するかを学ぶ方がよいでしょう。

0
tylerl

サーバーからクライアントにキーを転送するための独立した配布チャネルなしでは実行できません。 SSLの場合、これが証明書署名プロセス全体であり、Webブラウザーに含まれる認証局ルート証明書の公開鍵です。したがって、最初の問題は、man-in-the-middle攻撃(ネットワーク経由ではない)によって妨害されない方法でサーバーからクライアントにキーを取得する方法を考え出すことです。

0
Mike Scott