2

ここ数日、Bouncy Castle (java) をいじっていて、Diffie-Hellman 交換で秘密鍵を安全に交換できると確信できるところまで来ました。

暗号交換を適切に実装することの難しさを強調する多くの投稿を読んだので、私の仕事について率直な意見をお願いします. 基礎となるすべての暗号操作は Bouncy Castle に基づいているため、信頼できると見なされる場合があります。

    String message = "Hello World";

    AESCipher aes_client = new AESCipher(256);
    RSACipher rsa_server = new RSACipher(2048);

    // (Public key sent over the wire)
    RSACipher rsa_client = new RSACipher(rsa_server.getPublicKey().getModulus(),
                                         rsa_server.getPublicKey().getExponent());

    // The client encodes his AES key with the RSA public key:
    byte[] aes_key = rsa_client.encode(aes_client.getKeyBytes());
    byte[] aes_iv = rsa_client.encode(aes_client.getInitializationVector());

    // (Data sent back over the wire)
    byte[] decoded_aes_key = rsa_server.decode(aes_key);
    byte[] decoded_aes_iv = rsa_server.decode(aes_iv);

    // The server creates an AES server which uses the client key:
    AESCipher aes_server = new AESCipher(decoded_aes_key, decoded_aes_iv);

    byte[] encoded_message = aes_client.encode(message.getBytes());
    byte[] decoded_message = aes_server.decode(encoded_message);

    System.out.println(new String(decoded_message));

この交換は安全と見なすことができますか? ハードワークを台無しにするのは痛いですが、SSL Sockets を使い続ける必要がありますか? ご意見をお寄せいただきありがとうございます。

(ちなみに、私の Bouncy-Castle-Wrapping-Library は完全にオープンソースなので、リポジトリの URL が必要な場合はお知らせください。)

4

2 に答える 2

2

(あなたのプロトコルには Diffie-Hellman はなく、RSA と対称暗号化だけです。)

最初の基本的な注意点は、プロトコルがアクティブな攻撃に対して脆弱であるということです。「中間者」は古典的です (攻撃者は公開鍵を傍受し、それを自分のものに置き換えます)。また、対称暗号化のみがあり、MAC はありません。攻撃モデルが受動的な攻撃者のみに関するものであると仮定しましょう。ほとんどの場合、これは控えめに言っても非常に大胆な仮定です。実際のところ、これが当てはまる状況を想像するのは困難です。盗聴者は、送信されたバイトを見ることはできますが、自分のメッセージを送信することはできません。整合性チェックを使用して認証済みトンネル内ですべてを実行しない限り (SSL にはそのためのモードがありますが、この種のポイントは無効になります)。

必要のない IV を暗号化しています (IV は鍵ではありません。それ以外の場合は、IV ではなく「鍵」と呼ばれます)。IV に必要なのは、暗号化されたメッセージごとにランダムに生成されることです。CBC モードを使用すると仮定すると、メッセージの最後の暗号化ブロックが次のメッセージの IV として使用されても問題ありません。ただし、同じ対称暗号化キーを持つ 2 つの異なるメッセージに IV を再利用するのは致命的です。Bouncy Castle には という名前のクラスがないためAESCipher、サンプル コードでは、AES を適切なチェーン モードと正しい IV 管理で使用しているかどうかがわかりません。また、前のメッセージからの最後の暗号化ブロックの再利用は、メッセージが連続して送信され、メッセージが失われない場合にのみ機能することに注意してください。より堅牢なソリューションは次のとおりです。

  1. java.security.SecureRandomメッセージごとに新しいランダム IV を (暗号的に強力な RNG などを介して) 選択します。
  2. 暗号化されたメッセージとして、IV と暗号化されたデータの連結を送信します。

これにより、受信者は IV を (最初のメッセージ ブロックとして) 回復し、前のメッセージが送受信されたかどうかに関係なく、メッセージを処理できます。ここでも、アクティブな攻撃者は、単純な「リプレイ攻撃」 (攻撃者が以前に送信したメッセージのコピーを送信する) によってのみ、そのスキームに大混乱をもたらす可能性があります。

補足として、クライアントとサーバー間で異なる可能性があるプラットフォームのデフォルトのエンコーディングString.getBytes()を使用してください。new String(byte[])UTF-8:message.getBytes("UTF-8")new String(decoded_message, "UTF-8").

一般的に言えば、セキュリティと傲慢はうまく混ざりません。コードを捨てる準備をしてください。SSL/TLS などの標準プロトコルを実際に使用する必要がある主な理由は、セキュリティを証明できないためです。プロトコルが安全であると考える理由を誰か (上司など) に尋ねられたら、あなたは何と答えますか? 「スタックオーバーフローの誰かが私にそう言った」?

于 2011-03-15T11:08:18.317 に答える
0

IV は通常、暗号化されていないことを指摘しておきます。害はないと思いますが、必要ありません。

于 2011-03-14T18:51:59.230 に答える