私の個人的な調査では、メッセージングアプリを作成する必要がありますが、セキュリティは、アプリケーションの重要な部分であるMITM(中間者攻撃)からのセキュリティ、デバイスエンド、およびサーバーレベルでのみです。 (注:電報のようなクロスデバイスアクセスのためにサーバーにメッセージをバックアップしたいので、これはエンドツーエンドの暗号化ではありません)。
次のモデルを作成しました。
salt_key
salt_key
(AES)salt_key
サーバーの公開鍵(RSA)salt_key
RSA秘密鍵とメッセージsalt_key
秘密鍵を使用して、メッセージを復号化します。これは安全な方法ですか、それともメッセージングアプリを安全にする別の方法ですか?
さて、あなたの提案を見てみましょう:
考慮すべきその他のポイント:
これは実際には正反対です。これは、メッセージを処理するための安全ではない方法です。私の後に繰り返します。「私のサーバーは、「secure」メッセージの内容を読み取ることができませんever。 」すべてを暗号化してサーバーに送信し、サーバーはそれを再暗号化して他のユーザーに送信します。サーバーが侵害された場合、システム全体が侵害されます。
代わりに、メッセージを2つの別個の部分として考える必要があり、概念的にシンプルに保つために、昔ながらのカタツムリメールとして考えます。封筒と手紙があります。封筒は郵便配達員/郵便局(サーバー)で読み取ることができますが、封筒を開いたり、手紙を読んだりすることはできません。これは最終的な受信者専用です。あなたが説明するシナリオでは、それは郵便局がメッセージを読むことができるポストカードのようなものです(あなたはそれを望まないでしょう)。
代わりに、このようなシナリオを検討してください。
2つの機能を処理するサーバーがあります:メッセージ配信(+オフラインクライアントを待機中のストレージ)と受信者の検索。中央サーバーに接続するクライアントがあり、そのすべての仕事はメッセージの暗号化と復号化(およびローカルストレージ/メッセージのファイリング)です。
リストしたケースに対するセキュリティを確保するには、多層の保護が必要です。すべての通信は、中間者攻撃(TLSの完全一致のように聞こえる)を防ぐために、トランスポート暗号化リンクを介する必要があります。サーバーは自身のRSAキーペアを生成し、受信者の検索機能として、このキーの公開コンポーネントを独自の内部ディレクトリに公開する必要があります(ユーザー名と衝突することのない予約済みの名前を持つプローブ)。各クライアントは、メッセージ保護のためにRSAスタイルの鍵ペアも生成する必要があります(または、既存の鍵ペアをインポートします。アカウントに複数のクライアントを参加させたい場合は、各クライアントに同じ鍵ペアをインポートします)。このキーが生成されたら、パブリックコンポーネントをサーバーに送信する必要があります(ルックアップ値とともに、ユーザー名または電子メールアドレスを検討してください)。次に、サーバーはこのキーを公開ディレクトリに追加します。重要なセキュリティ機能は、サーバーがルックアップ値を公開鍵IDに(および公開鍵IDを完全な公開鍵に)変換できることです。これを2つのステップに分割して、不要なデータ転送を回避し、処理を高速化します。ただし、サーバーは公開鍵のID /データを受け入れてルックアップ値を返すべきではありません(暗号化キーを使用すると、公開ユーザーはキーが誰に属しているかをルックアップできません)。
メッセージを送信したいときはいつでも、クライアント側で目的の受信者を配置します。クライアントは、各受信者を検索してキーIDを取得します。クライアントがすでにローカルキャッシュに対応する公開鍵を持っている場合は、それらを使用します。それ以外の場合は、サーバーに完全なpub-keyデータを(IDで)要求し、それをキャッシュ/使用します。送信時に、クライアントは複数の暗号化を行います。1つはエンベロープ(サーバーの公開鍵を使用して受信者キーIDのリストを暗号化します)ともう1つはレター(メッセージ自体は暗号化されますが、サーバーではなく受信者に対してのみ暗号化されます) )、最後にそれらのそれぞれの署名(サーバーが配信する必要がある正当なメッセージであることをサーバーが確認できるようにし、受信者がメッセージが転送中に改ざんされていないことを確認できるようにします)メッセージはサーバーに送信され、サーバーはエンベロープデータを復号化し、メッセージのコピーを各ユーザーの配信キューに(ユーザー名/電子メールではなく公開キーIDで)配信キューに入れます。
定期的にクライアントはサーバーに照会して、待機しているメッセージがあるかどうかを確認する必要があります。クライアントがランダムなメッセージに秘密鍵で署名することを要求することにより、サーバーはクエリを検証する必要があります(そのため、メッセージが暗号化されていても、間違った人にメッセージを配信しないでください)。サーバーにランダムエントロピーを高くするのに十分なサイズのランダムバイト配列を生成させ、クライアントに秘密鍵(サーバーに保存されている公開鍵のコピーで検証可能)で署名するように依頼してから、リクエストへのメッセージを解放します。クライアント。サーバーにすべてのメッセージのバックアップを含めたい場合は、サーバーにメッセージ全体(封筒と手紙)を保存してもらいます。セキュリティ上の理由から、サーバーは「手紙」を復号化しませんが、任意の場所に再送信できます。チェックインしているクライアント(クライアントが同じキーペアを共有している場合は、同じメッセージセットをダウンロードし、クライアント側で復号化できます)
クライアントは、ダウンロードされたメッセージを取得すると、秘密鍵を使用してローカルで復号化し、「文字」をエンドユーザーに表示できます。これにより、メッセージ自体がサーバーから見えないことが保証され、元のデザインにあったセキュリティホールが埋められます。
基本的に、PGPキーサーバー、MTA、ストレージポイントなどのサーバーを使用します。クライアントを暗号化エンドノードにします。サーバーは、検索する値(username/email/etc)が提供されていれば、任意のユーザーの公開鍵データを検索できます---しかし、公開鍵データからの検索値は提供しません(これにより、誰かが検索するのを防ぎますメッセージエンベロープが危うくなった場合に誰が通信しているか)。すべてのメッセージコンテンツはクライアント間で直接暗号化されます(これにより、サーバー側の攻撃がメッセージコンテンツを危険にさらすことが防止されますが、サーバーにはキーIDをルックアップ値にマップするデータベースがあるため、攻撃者は誰が通信しているのかを知ることができます) 。エンベロープは送信者によって署名されます。これにより、送信が正当な送信元からのものであることがサーバーに確認されます(そうでない場合、メッセージは攻撃の試みとして破棄されます)。そして、手紙は送信者によって署名され、これにより受信者はメッセージが実際に送信者からのものであることを確認できます(MitMまたはサーバー側の攻撃が、実際には送信者からのものではない「受信者」にメッセージを送信することを防ぎます)。
これらすべてを適切な対策のためにTLS内に階層化すると(MitM攻撃を防ぐのに役立ちます)、かなり安全なシステムができあがります。 「秘密鍵データをパスワードで保護する」(侵害されたクライアントノードが保存されたメッセージコンテンツをすぐに提供しないようにする)、または時間ベースのエンベロープ/文字の有効期限(メッセージが一時的であり、非表示になる)などを追加することで、時間を短縮できます持続しない)。サーバー側では、メモリにのみ存在する暗号化されたデータとしてすべてのキューを保持することも考えられます(誰かがサーバーを盗んでサーバーを離れようとすると、キーをブルートフォースする時間があるため、電源が失われますサーバー上にあるメッセージも失われ、物理サーバー攻撃の効果が低下します)
これは完全なダブルラチェットシステムほど強力ではありませんが、ほぼ同じです。そして、実装するのはかなり簡単です(RSAキーとPGP en/de-cryptionは、プロジェクトにドロップするのが比較的簡単な既知のプロセスです)。