シック クライアント アプリケーションでの API 秘密キーの保護

StackOverflow https://stackoverflow.com/questions/33288

  •  09-06-2019
  •  | 
  •  

質問

アプリケーション内で、API 呼び出しのハッシュを計算するために使用する秘密キーを取得しました。.NET アプリケーションでは、Reflector などのプログラムを使用してアセンブリから情報を取り出し、これらのキーを含めることは非常に簡単です。

アセンブリを難読化することは、これらのキーを保護する良い方法ですか?

役に立ちましたか?

解決

おそらくそうではありません。

暗号化と Windows の組み込み情報隠蔽メカニズム (DPAPI や ACL で制限されたレジストリ キーへのキーの保存など) を調べてください。これは、アプリケーションと同じシステム上に維持する必要があるセキュリティを確保するのと同じくらい良いことです。

物理的にマシンの前に座っている誰かがあなたの情報を入手するのを阻止する方法を探しているなら、それを忘れてください。誰かが自分の管理下にないコンピュータに無制限にアクセスできると決めた場合、あらゆる状況下でデータが保護されていることを 100% 確信する方法はありません。決意のある人は、その気になれば必ずそれを成し遂げるでしょう。

他のヒント

(少なくとも私が理解しているように) 難読化すると、単にメソッド名をいじってコードを理解するのが難しくなります (しかし不可能ではありません) ので、私はそうは思いません。これは実際のキーのデータを変更しません(どこかに定数に保存したと思います)。

もう少し見にくくしたいだけの場合は、平文に単純な暗号 (ROT-13 など) を実行して、少なくともコード自体に平文で保存されないようにすることができます。しかし、だからといって、決意を固めたハッカーがあなたのキーにアクセスすることを阻止できるわけではありません。より強力な暗号化方法は役に立ちません。そのためのキーをコードに格納する必要があり、それを保護するものが何もないからです。

私が考える唯一の本当に安全な方法は、何らかの方法でキーをアプリケーションの外部に保持し、キーへのアクセスを制限することです。たとえば、キーを別のファイルに保存し、そのファイルを OS レベルのユーザーベースの制限で保護できます。それはおそらくうまくいくでしょう。データベース接続でも同じことを行うことができます (ここでも、ユーザーベースのアクセス制限を利用して、権限のないユーザーがデータベースにアクセスできないようにします)。

自分のアプリでこれを実行するというアイデアを考えてみましたが、実装したことはありません。

DannySmurf 氏は、アプリケーションを実行している人からキーを隠すことはできないという点で正しいです。アプリケーションがキーにアクセスできれば、人もキーにアクセスできるようになります。

しかし、正確に何を達成しようとしているのでしょうか?

それが何であるかにもよりますが、単にユーザーのマシン上で秘密を「秘密」に保つことに依存するだけではなく、目的を達成する方法が存在することがよくあります。

ここで試合に遅れます...

キーをアセンブリ/アセンブリ構成に保存するアプローチは、基本的に安全ではありません。特定のユーザーがアクセスすることになるため、これを保存する鉄則的な方法はありません。地球上で最高/最も高価な難読化製品を使用しているかどうかは気にしません。データを保護するために PDAPI を使用するかどうかは気にしません (ただし、PDAPI を使用した方が良いです)。OS で保護されたローカルのキー ストアを使用するかどうかは気にしません (これはさらに良いことです)。すべてが同じ中核的な問題を抱えているため、どれも理想的ではありません。ユーザーはキーにアクセスでき、キーは数日、数週間、場合によっては数か月、数年にわたって変更されずにそこにあります。

はるかに安全なアプローチは、実証済みの真の PKI を使用して API 呼び出しを保護することです。ただし、API 呼び出しが頻繁に行われる場合、パフォーマンスに明らかなオーバーヘッドが生じますが、大部分のアプリケーションではこれは問題ではありません。

パフォーマンスが懸念される場合は、非対称 PKI 上で Diffie-Hellman を使用して、AES などの暗号で使用する共有秘密対称キーを確立できます。この場合の「共有」は、すべてのクライアント/ユーザーではなく、クライアントとサーバーの間で共有されることを意味します。ハードコーディング/ベイクインされたキーはありません。どこでも。

キーは一時的なもので、ユーザーがプログラムを実行するたびに再生成されます。あるいは、本当に偏執的な場合は、タイムアウトして再作成が必要になる可能性があります。

計算された共有秘密対称キー自体は、メモリのみの SecureString に保存されます。これらは抽出するのが難しく、たとえ抽出できたとしても、有効なのは非常に短期間であり、特定のクライアント (つまり、そのセッション) 間の通信にのみ有効です。言い換えれば、誰かがローカルキーをハッキングしたとしても、それはローカル通信を妨害する場合にのみ有効です。コード/構成を介してすべてのユーザーが共有する組み込みキーとは異なり、この知識を使用して他のユーザーに影響を与えることはできません。

さらに、キー全体がネットワーク上に渡されることは決してありません。クライアントのアリスとサーバーのボブは独立してそれらを計算します。これを行うために彼らが渡す情報は、理論的には第三者のチャーリーによって傍受される可能性があり、チャーリーが独自に共有秘密鍵を計算できるようになります。そのため、(大幅にコストがかかる) 非対称 PKI を使用して、アリスとボブ間の鍵生成を保護します。

これらのシステムでは、キーの生成が認証、つまりセッションの作成と組み合わせて行われることがよくあります。PKI を介して「ログイン」して「セッション」を作成すると、それが完了すると、クライアントとサーバーの両方が独立して対称キーを持ち、そのセッションでの後続のすべての通信の桁違いに高速な暗号化に使用できます。大規模サーバーの場合、これは、すべてに TLS を使用するよりも復号化の計算サイクルを節約するために重要です。

ちょっと待って:私たちはまだ安全ではありません。メッセージの読み取りを禁止しただけです。

中間者による操作を防ぐために、メッセージ ダイジェスト メカニズムを使用する必要があることに注意してください。送信されているデータを読み取ることは誰にもできませんが、MD がなければデータの変更を妨げるものはありません。したがって、暗号化する前にメッセージをハッシュし、そのハッシュをメッセージと一緒に送信します。次に、サーバーは復号化時にペイロードを再ハッシュし、メッセージの一部であったハッシュと一致することを確認します。メッセージが転送中に変更された場合は変更されず、メッセージ全体が破棄または無視されます。

防御するために必要な最後のメカニズムはリプレイ攻撃です。この時点で、ユーザーによるデータの読み取りやデータの変更は阻止できましたが、単純にデータを再送信することは阻止できませんでした。これがアプリケーションにとって問題となる場合は、そのプロトコルがデータを提供する必要があり、クライアントとサーバーの両方がリプレイを検出するのに十分なステートフル情報を持っている必要があります。これは、暗号化されたペイロードの一部であるカウンターのような単純なものである可能性があります。UDP などのトランスポートを使用している場合は、おそらく重複したパケットを処理するメカニズムがすでに備わっているため、リプレイ攻撃にもすでに対処できることに注意してください。

明らかなことは、これを正しく行うのは簡単ではないということです。したがって、絶対に使用できない場合を除き、PKI を使用してください。

このアプローチは、ハッキングや覗き見からのセキュリティを確保しながら、より高いスケーラビリティを実現するために各プレイヤーのコンピューティングをできるだけ少なくすることが非常に望ましいゲーム業界で頻繁に使用されていることに注意してください。

結論として、これが本当に懸念事項である場合は、API キーを安全に保存する場所を探すのではなく、そうしないでください。代わりに、アプリでこの API を使用する方法を変更します (当然、両方の側を制御できると仮定します)。PKI を使用するか、PKI が遅すぎる場合は PKI 共有対称ハイブリッドを使用します (これは最近ではほとんど問題になりません)。そうすれば、セキュリティ上の問題となるものは何も保存されなくなります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top