web-dev-qa-db-ja.com

JavaScript Diffie-HellmanおよびAESプロトコル

BigInteger Javascript library を使用して、Diffie-Hellmanプロトコルを使用して対称鍵を作成しています。 128、160、192ビットのキーを作成したい。いくつかの調査の結果、Diffle Hellman 2048ビットを使用する必要があることがわかりましたが、

  • D-Hパラメータのビット長は、p、g、a(およびb)ですか?私は現在p 2048ビットとa、b 256ビットを使用していますが、それでいいですか?
  • プロトコルの最後にBigInteger 2048ビットのキーを取得しましたが、それから128、162、または192ビットのキーをどのようにして導出できますか?

また、AES-128/160/192を使用してメッセージを暗号化/復号化するために Stanford Javascript Crypto library を使用しています。 AESは引数として、タイプbitArrayまたは文字列のキーを受け取ります。

  • 128ビットのBigIntegerキーを取得したら、それをAESプロトコルでどのように使用できますか?

最初はBigIntegerキーを文字列キーに変換し、それをAESで使用することを考えましたが、それは正しくないと思います。関数sjcl.encrypt(key、message)が文字列の場合にキーを変換する方法がわからないため、utf8StringからbitArrayに変換すると、キーは128ビットではなく、はるかに多くなります。したがって、私はBigIntegerキーをbitArrayキーに変換するのが最善の方法だと思います。もしそうなら、あなたはそれをどのように行うのか考えがありますか?

そうでなければ、DHプロトコルを使用できるライブラリを知っていて、スタンフォードライブラリにうまく適合している場合は...

ご協力ありがとうございました。

編集:私は自分の暗号を発明していません、私は HCBKプロトコル を実装しています。これは信頼性を提供します。

5
Kheil

D-Hパラメータのビット長は、p、g、a(およびb)ですか?私は現在p 2048ビットとa、b 256ビットを使用していますが、それでいいですか?

DHKEは離散対数問題(DSAおよびElGamalと同じ)に基づいているため、サイズは適切です。

プロトコルの最後にBigInteger 2048ビットのキーを取得しましたが、それから128、162、または192ビットのキーをどのようにして導出できますか?

100%確実ではないことを認めざるを得ません。安全にしたい場合は、ハッシュしてから、ハッシュ関数の出力から16バイトまたは24バイトを取得します。または以下を参照してください。

128ビットのBigIntegerキーを取得したら、それをAESプロトコルでどのように使用できますか?

Stanford Crypto Libraryは、高レベルの暗号化関数を実際にエクスポートします(sjcl.json.encrypt)、これは引数として暗号文とパスワードを受け取ります。前のステップの2048ビットのキー全体をパスワードとして渡すだけで済みます。これは、ブロックモードとIVの生成も処理します。


(そして私が答える唯一の理由はこれをあなたに伝えるためです)、それがあなたがすべてを間違っていることに注意してください。まず、自分の crypto(-graphic protocol) を実行しています。 Diffie-Hellmanは、教科書モードでは でも安全ではありません 。さらに、 JavaScript暗号は安全ではありません 。スクリプトを安全に配信するにはHTTPSが必要です。HTTPSを使用している場合は、これ以上暗号化する必要はありません。

本番環境で暗号を実行する前に、すべてのリンクを読んでよく考えてください。

7
copy

私は教育的な関心のためにこのメッセージを書きます。私は強く希望します自分の暗号プロトコルと実装を一緒に平手打ちすることを想定しておらず、それを本番環境に配備します道。


Diffie-Hellman はグループで行われるプロトコルです。 「プレーンな」DHは、与えられた素数pを法とするゼロ以外の整数のサブグループで機能し、グループ法則として乗算を行います。だからあなたは持っています:

  • モジュラス、大きな素数p
  • 「ジェネレータ」g、これはpを法とする整数で、次数rを持ちます

gは0または1であってはなりません。gの順序は、最小の非ゼロ整数rですそのgr = 1modprの最大の素因数であるqを呼び出しましょう。pおよびgが最初にどのように生成されるかに応じて、r = q(つまり、gの順序が素数です)。

DHをセキュリティで保護するには、pqの両方が十分に大きく、 離散対数 にする必要があります。実現不可能。これは、「大」の概念とは異なります。大まかに言えば、pは2048ビット長、qは256ビット長程度にする必要があります。g自体には条件はありません。g = 2は、次数が十分大きい素因数qを認める順序のサブグループを生成する限り、悪影響を与えることなく使用できます。

DHでは、パーティXはランダムなx(理想的にはqを法として一様に選択された整数ですが、ランダムな256ビット整数でもかまいません)を生成して計算し、gを送信するバツmodpをパーティーYに送信します。同様に、Yはyを生成してgを送信しますymodpto party X.「共有シークレット」は値z = gxymodp、XとYの両方で計算できます。値zは整数モジュロpであり、実際にはgによって生成されるサブグループのメンバーです。ただし、XとYには「対称キー」、つまりある程度の均一性を持つビットのシーケンスが必要です。エントロピーを失わずに、数学的な構造を隠しながら適切なサイズの値を生成する変換が必要です。通常の方法は、zを一連のバイトにエンコードすることです(256バイトは1..p範囲の数値であるため、pの長さは2048ビットです)、次にハッシュを適切なハッシュ関数(たとえば、SHA-256)でハッシュします。これにより、ハッシュ出力が生成され、必要なサイズ(128ビットなど)に切り捨てることができます。

未加工のDHには認証が含まれていないことに注意してください。少なくとも1つの場合を除き、 中間者攻撃に弱い パーティ(クライアントなど)には、サーバーからの正しいDHパブリック値があり、偽のパブリック値がないことがある程度保証されています。 DHはその保証を提供しません。

また、128ビットの共有キーを取得すると、問題が解決するわけではありません。適切な対称暗号化はhardです。 [〜#〜] aes [〜#〜] などのブロック暗号は、messages自体を暗号化しないプリミティブです。 操作モード で使用する必要があります。これには、適切に生成された [〜#〜] iv [〜#〜] などの追加要件があります。また、整合性のために、ある種の [〜#〜] mac [〜#〜] も必要になります。暗号化とMACの組み合わせは 微妙な問題 です。プロトコル全体では、 リプレイ攻撃 と個々のパケットの並べ替えを回避するための準備も必要です。

基本的に、 [〜#〜] ssl [〜#〜] のようなものを構築する必要があり、これらすべての詳細を処理します。だから、これは疑問を投げかけます:なぜあなたはSSLを使わないのですか? Javascriptは、完全なSSL実装(URLがhttps://で始まる場合に使用されるもの)がすでに含まれているWebブラウザーで実行されます。

3
Thomas Pornin

誰もが言うように、安全な方法で他の暗号システムと大部分がつながっていても、専門家が分析して暗号システムを解読するようにしてください。それでも、私はそれを潜在的に安全でないアプリケーションとして扱い、「おもちゃ」のニーズにのみ使用します(openssl/GPGなどのよく知られたツールと比較して同等に吟味されていると考えているのではなく)-そしてこれらのツールでさえ広く公表されています欠陥は数年後に発見されました)。個人的には、暗号化ハッシュ(SHA-256は64ビットを超える暗号化はできないと考える)に慣れていないようです。そのため、暗号化について1、2コースを受講することを強くお勧めします。 (Courseraには、Dan Bonehによる two すばらしい courses があり、そしてudacityには Applied Cryptography で良いコースがあります).

JavaScript暗号ライブラリを非常に弱い方法で使用するのは非常に簡単です。

  • ユーザーにWebページにアクセスさせ、そのWebページからhttpを介してJavaScriptファイルを提供して暗号化を実行します(たとえば、ユーザーがフレーズを入力し、キーを取得して暗号化されたメッセージを生成するパスフレーズを入力します)。これにより、攻撃者がJSファイルを変更することは簡単になります。
  • Httpsを使用して配信しても、配信サーバー側の誰もがファイルを改ざんしてセキュリティを危険にさらす可能性があります。したがって、このシナリオでは基本的に、サーバーがセキュリティを危険にさらす可能性のある方法でJavaScriptファイルを変更することができます。

ただし、javascript(実際にはECMAScript)は単なるプログラミング言語です。これは、新しく提供されたページからWebブラウザーで使用されるだけではありません。これは、長期間有効なブラウザ拡張機能(信頼できるソースからSSL経由で1回ダウンロードし、OpenSSLまたはGPGを最初に信頼できるソースから一度ダウンロードし、インストールして繰り返し実行する方法と同様の方法で何度も実行)で使用できます。シェルの別のスクリプト言語(node.js)。 「JS暗号は安全ではない」という主張は、「python暗号は安全ではない」とほぼ同じであり、「C++暗号は安全ではない」と言っても過言ではありません。

私は特に 知識の前のハッシュコミットメントプロトコル に精通していません(そして、あなたが言及したリンクが右上の特許の制限について話していたので、それについて学ぶことに本当に興味がありません)ので、はるかに単純なシナリオを分析しますJS暗号を使用できる場所。

アリスとボブの両方がパスフレーズ(自分で設定、ダイスウェアディクショナリからランダムに生成)を共有し、適切なパスワードベースのキー導出関数(たとえば、SHA-512の5000ラウンドと最初の256ビットを取る)と対称暗号化プロトコルに同意しました(AES-256ランダムCTRモード)。クラウドサービス(GoogleドライブやDropbox、Amazon Webサービスなど)を使用して暗号化されたデータを保存したいのですが、安全なローカルの非共有コンピューターにJavaScript暗号化/復号化スクリプトのみを保存します。原則として、JS暗号ライブラリーを使用してAES-256を実行し、ブラウザー拡張機能としてWebブラウザーに保存することができます。パスフレーズを入力するとキーが生成され、メッセージ/ファイルを暗号化または復号化できる同じブラウザー拡張機能を両方のコンピューターに保存できます。

この種のシナリオでは、クライアント側のローカルキー生成フェーズでのタイミング攻撃は、キーの生成が開始されたときにネットワーク情報が送信されない限り、無関係です。リプレイ攻撃は重要な場合がありますが、メッセージには暗号化されたタイムスタンプが含まれる可能性があります(したがって、「$ 100をアリスからボブに送金:2013年7月4日正午に」というメッセージを繰り返した場合、既にアクションを繰り返すことはありません。 7月4日にアクションを実行しました)。はい、攻撃者がブラウザ拡張機能を備えたコンピュータにアクセスして悪意を持って変更することは簡単です(たとえば、キーロガーを追加し、キーを記録/誰かに送信します)。しかしこれは、攻撃者が侵入先のマシンにキーロガーをインストールしたり、OpenSSLのソースコードをダウンロードしてコンパイルしたり、OpenSSLを侵入先のバージョンに置き換えたりすることとそれほど変わりません。繰り返しになりますが、暗号化/復号化に使用しているコンピューターが危険にさらされている場合でも、暗号システムを安全に保つことができるとは期待しないでください。

ブラウザ拡張機能として付与された場合、AJAX呼び出しを介して誤って情報を漏らさないように十分注意する必要があります。Webブラウザは、同時に実行される多くのJavaScriptファイルで動作します。たとえば、 AESでGmailメッセージを暗号化したいと言います。mail.google.comに移動し、[作成]を押し、作成ウィンドウでメッセージを入力し始め、メッセージを終了し、メッセージ本文のプレーンテキストをAES-に置き換えるブラウザ拡張機能を実行します暗号化された暗号文を入力し、送信を押します。これは安全ではありません。Gmailは、作成中にドラフトをAJAXコールを介して、作成ウィンドウでサーバーに自動的に送信します(ドラフトとして保存するために接続が切断されます)。


PS:単純なAES暗号化スキームに故意に欠陥があり、中間者がメッセージを「夜明けの攻撃」から「夕暮れの攻撃」に非常に簡単に変更できるメッセージ認証が存在しませんでした。 (もともと私はこれを指摘するつもりはありませんでしたが、暗号化が微妙であるという点を繰り返すようにしています)。

1
dr jimbob