UDPを使用してネットワーク経由で1秒あたり数個の小さなデータを送信する必要があるアプリケーションがあります。アプリケーションは、データをリアルタイムで送信する必要があります(待機なし)。これらのデータを暗号化して、私が行っていることが可能な限り安全であることを保証したいと思います。
私はUDPを使用しているため、SSL/TLSを使用する方法がありません。プロトコルがコネクションレス/信頼性/規制されていないため、各パケットのみを暗号化する必要があります。
現在、ユーザーからのパスフレーズから派生した128ビットキーと、CBCモードのAES(AES-CBCを使用するPBE)を使用しています。パスフレーズにランダムソルトを使用して128ビットキーを導出し(パスフレーズに対する辞書攻撃を防止)、もちろんIVを使用する(パケットの統計分析を防止する)ことにしました。
しかし、私はいくつかのことを心配しています:各パケットには少量のデータ(パケットごとに2つの整数値など)が含まれているため、暗号化されたパケットは既知の平文攻撃に対して脆弱になります(これによりキーの解読が容易になります) 。また、暗号化キーはパスフレーズから派生しているため、キースペースが大幅に少なくなります(ソルトが役立つことはわかっていますが、一度ネットワーク経由でソルトを送信する必要があり、誰でも取得できます)。これら2つのことを考えると、誰でも送信されたデータを盗聴して保存し、鍵を解読しようとすることができます。このプロセスには時間がかかる場合がありますが、キーが解読されると、保存されているすべてのデータが復号化されます。これは、私のアプリケーションにとって実際の問題になります。
だから私の質問は、コネクションレス型プロトコル(UDP)を使用して連続的な小さなデータを送信/暗号化するためのベストプラクティスは何ですか?私の方法はそれを行うための最良の方法ですか? ...流れた? ...やり過ぎ?
私は100%安全な解決策を求めているわけではないことに注意してください。そのようなものはありません。
いくつかの選択肢があります。データグラム用に適応されたTLSのバージョンであるDTLSを使用できます。 [〜#〜] rfc [〜#〜] で指定され、opensslライブラリに実装されます。 IKE/IPsecプロトコルを使用して、IPsec部分のUDPカプセル化を使用することもできます。通常、IPsecはOSレベルで利用できます。 OpenVPN を使用することもできます。これは、鍵交換用のTLSと独自のUDPベースのパケット暗号化プロトコルのハイブリッドのようです。
データが小さすぎることが問題である場合は、ランダムなバイトでデータを拡張するのはどうですか?これにより、平文を推測するのがはるかに難しくなります。
この質問は少し古いですが、 ワンタイムパッド タイプのアプローチを使用するのはどうですか?安全で信頼性の高いトランスポートメカニズム(HTTPSなど)を使用して、サーバーからクライアントにワンタイムキーを送信できます。キーのセットは2つあります。1つはクライアントから切断用、もう1つはサーバーからクライアント用です。各データグラムには、シーケンス番号(ワンタイムキーの識別に使用)と暗号化されたメッセージが含まれます。各キーは1つのデータグラムにのみ使用されるため、小さなデータの問題にさらされることはありません。とはいえ、私はこのようなものの専門家ではないので、使用する前に必ずこのアイデアをチェックしてください...
パスワードの代わりにEcdhキー交換を使用します(パスワードを使用してクライアントの秘密キーを暗号化します。クライアントに残します)。これは非常に強力な鍵です。
Aescbcは役に立ちません。メッセージが短すぎるため、リプレイ攻撃を防ぎたい。 64ビットメッセージ(2つの整数)にカウンター(0から始まる)を埋め込みます。64ビットは、2 ^ 64メッセージを送信できることを意味します。ブロックを2回暗号化し(aes ecb)、e(k; m | count)| e(k; e(k; m | count))を送信します。受信者は、2番目のブロックが最初のブロックの暗号化である単調に増加するカウントのみを受け入れます。これらは、udpパケットにうまく収まる32バイトのメッセージです。
2 ^ 64メッセージが小さすぎる場合。メッセージを小さくできるかどうかを確認します(3バイト整数はカウンターが80ビットになる可能性があることを意味します)。または、制限に近づいたら(たとえば、2 ^ 64-2 ^ 32)、手順1(少なくとも片側の新しい秘密鍵)に戻ります。