シナリオ:
これは、クライアントからサーバーに特定の情報を送信する必要があるために行われますが、サーバーの内部動作の詳細が明らかになるため、これらの情報をクライアントに漏らしたくありません。
ここでの問題は、特定のユーザーが特定のページを表示するたびに、同じトークンが生成されることです。同じリクエストをエンドポイント広告で無限に再生できるようにすることとは別に、これにより、誰かがトークンの暗号化を破ることができる可能性が高くなります(そうです、可能性は低いですが、可能です)。
暗号化をさらに弾力性のあるものにするために、私の意図は、高品質のランダムな値を挿入することです。たとえば、GUID-暗号化される前にトークンに挿入します。最終的には、より多くのエントロピーが導入されます暗号化プロセスに入れます。つまり、気にする特定の同一の値のセット(つまり、ランダムな値を除くすべて)に対して、生成されるトークンはほぼ確実に異なります。このランダムな値は常に同じ場所に挿入され、常に同じ長さなので、トークンが復号化された後でトークンを削除して捨てるのは簡単です。事実上、これにより暗号化が難読化されます。
これは私の問題に対する比較的単純で安全な解決策であると私の訓練されていない目に見えますが、それは私が時間を無駄にしたり、物事の安全性を低下させたり複雑にしたりしていますか?
暗号化されたトークンにランダム性を追加する必要はありません。適切に暗号化されている場合、ユーザーは暗号化されたデータについて何かを推測する方法がありません。
ここでの問題は、特定のユーザーが特定のページを表示するたびに、同じトークンが生成されることです。
これは奇妙に思えます。暗号化は安全な標準を使用していないようです。そうしないと、同じトークンを暗号化するたびに、暗号文が変更されます。 IVを使用する必要があり、AES-ECBについて決して考えないでください。そのモードは壊れており、AESの仕組みを子供たちに教えるためにも使用しないでください。
業界標準を使用している場合は、 初期化ベクトル (IV)について理解できます。大まかに言えば、IVは暗号文を変更するプロセスに追加される値であるため、同じ鍵で2つの同一の平文を暗号化しても、対応する暗号文は変更されます。
IVは、追加を検討しているランダムデータです。それはすでにそこにあります。
これを分解してみましょう:
問題:トークンの再生:
同じリクエストをエンドポイント広告で無限に再生できるようにする以外に
通常、認証トークンはトークンを期限切れにすることでこの問題を解決します。暗号化されたデータには日付スタンプが含まれ(各トークンを一意にするという副作用があります)、サーバーはたとえば15分より古いトークンをすべて拒否します。
問題:暗号を破る:
これにより、誰かがトークンの暗号化を破ることができる可能性が高くなります
私は専門家ではありませんが、暗号化ごとにランダムなIVを使用し、トークンの一部として暗号文とともにIVを含める必要があるように思えます。これは、暗示されている暗号解読の問題を解決し、トークンを一意にするという副作用をもたらします。 (ランダムIVを使用していない場合は、おそらくはるかに大きな問題が発生しています)
独自の暗号化スキームを設計するために深く掘り下げるのではなく、標準ライブラリを使用してこれを行ってみませんか? [〜#〜] jwt [〜#〜] をお勧めします。
最後に、公共サービスとしてこれを修正する必要があります:GUIDは高品質のランダム性ではありません。
Wikipedia/Universally_unique_identifier を参照してください。
UUID/GUIDはuniqueになるように設計されており、unpredictableになることはありません。 UUIDを取得するには、5つの標準的な方法があります。それらの4つは、MACアドレス+ホスト名+タイムスタンプのいくつかの組み合わせです。バージョン4のUUIDは純粋なランダムですが、UUID/GUIDの生成は高速で非ブロッキングである必要があるため、非暗号化乱数ジェネレーターを使用します。
暗号ランダム性のソースとしてUUID/GUIDを使用しないでください。代わりに、UNIXでは/dev/random
、JavaではSecureRandom
、またはOS /プログラミング言語で同等のものを使用してください。
選択した私のプラットフォームで使用されるソリューションは、「マネージドIV(初期化ベクトル)を使用した暗号化/復号化」です。つまり、暗号化すると、プレーンテキスト全体が暗号化された安全なIVで暗号化され、IVは暗号テキストの開始前にbase64形式で配置されます。復号化されると、IVは前面から引き出され、暗号文のIVとして使用されます。これは開発者にはすべて透過的です。 IVを公開することは完全に安全であることに注意してください。正しいキーでの復号化は間違ったIVで失敗状態になるためです。プログラミング言語に同様の機能がある場合は、それを使用してください。暗号化するたびにランダムなIVを生成することで、プレーンテキストに余分なデータを入れる必要がなくなります。
私には、これは XY問題 のように見えます。
秘密を保護する最善の方法は、誰にも秘密を教えないことです。トークンはサーバー側で生成されます。サーバーすでに知っていますデータ。次に、トークンをサーバーに再生します。サーバーには、サーバーすでに持っているのデータのみが含まれています。それは完全に不要です。
他の回答では、IVで暗号化を使用することにより、暗号化の問題を迅速かつ即座に修正できることが指摘されています。しかし、より良い解決策は、これを不必要にすることです。
サーバーはトークンを作成しますさまざまな値を使用して、サーバーのみが知っているキーを使用して(業界標準のアルゴリズムを介して、自社開発のものではなく)トークンを暗号化し、ページデータの一部として返します
これらの値を暗号化する代わりに、データベースに保存します。本当に必要な場合でも、これらの値を暗号化して保存することができます。ただし、暗号化された形式であっても、これらの値がサーバーから離れる必要はまったくありません。次に、真にランダムなトークン(CSPRNGを使用)を生成し、それをルックアップキーとして使用します。このトークンをクライアントに送信します。
トークンはページのリンクに埋め込まれています
そのために生成したランダムトークンを使用します。
クライアントがそのリンクをクリックすると、トークンがサーバーに送信され、復号化および解析され、値は何をすべきかを決定するために使用されます
値を復号化して解析する代わりに、トークンを使用してデータベースでそれらを検索します。できました。暗号化されたデータのみを保存した場合でも、もちろんそれを復号化する必要があります。
これは、複数のサーバーがある場合にも機能します。トークンがサーバーAで生成され、サーバーBに送信される場合、サーバーBにサーバーAへのセキュア接続を使用させ、サーバーAからのトークンを介してデータを要求します。このシナリオでも、データがクライアントに送信されることはありません。
これは、クライアントからサーバーに特定の情報を送信する必要があるために行われますが、サーバーの内部動作の詳細が明らかになるため、これらの情報をクライアントに漏らしたくありません。
内部状態が実装からリークすることはありません。これはすでにコードのにおいであり、アーキテクチャに欠陥があることを示す良いヒントです。