1. ホーム
  2. c++

[解決済み] C++で機密性の高い文字列を隠蔽するためのテクニック

2023-01-31 14:58:38

質問

C++アプリケーションに機密情報(非公開にしたい対称暗号鍵)を保存する必要があります。簡単な方法としては、次のようになります。

std::string myKey = "mysupersupersecretpasswordthatyouwillneverguess";

しかし、アプリケーションを実行する際に strings プロセス (またはバイナリ アプリケーションから文字列を抽出する他の任意のもの) を通してアプリケーションを実行すると、上記の文字列が表示されます。

このような機密データを見えなくするために、どのような技術を使うべきでしょうか?

編集してください。

OK、では、かなりの人が あなたの実行ファイルをリバース エンジニアリングすることができます。 - と言っています。これは私の嫌いなところなので、ここで少しわめき散らしてみようと思います。

なぜこのサイトのセキュリティ関連の質問の 99% (OK、少し誇張しているかもしれませんが) は、「完璧に安全なプログラムを作成する方法はありません」という激流で回答されているのでしょうか? セキュリティは、一方では完璧な使いやすさとセキュリティなし、もう一方では完璧なセキュリティと使いやすさの間のスライディング スケールなのです。

ポイントは、何をしようとしているか、そしてソフトウェアが実行される環境に応じて、そのスライディング スケール上の位置を選択することです。

私は軍事施設用のアプリケーションを作成しているのではなく、家庭用 PC 用のアプリケーションを作成しているのです。 . 信頼されていないネットワーク上のデータを、あらかじめ知られている暗号化キーで暗号化する必要があります。このような場合、曖昧さによるセキュリティで十分でしょう。確かに、十分な時間とエネルギーと技術を持った人なら、バイナリをリバースエンジニアリングしてパスワードを見つけることは可能でしょうが、どうでしょう?私は気にしません。

一流の安全なシステムを実装するのにかかる時間は、クラックされたバージョンによる売上損失よりも高価です (実際にこれを販売しているわけではありませんが、私の言いたいことはわかりますよね)。新しいプログラマーの間でのプログラミングにおけるこの青天井の "可能な限り最高の方法でやりましょう"というトレンドは、控えめに言っても愚かなことです。

この質問に時間を割いて回答していただき、ありがとうございます - これらは非常に役に立ちました。残念ながら、私は 1 つの回答しか受け入れることができませんが、有用な回答はすべてアップロードしておきました。

どのように解決するのですか?

基本的には、プログラムとデバッガにアクセスできる人なら誰でも ができます。 意志 はアプリケーションでキーを見つけようと思えば見つけられます。

を実行したときにキーが表示されないようにしたいだけならともかく、そのような場合は strings を実行したときにキーが表示されないようにするだけなら、例えばキーが印刷可能な範囲にないことを確認することができます。

XORでキーを隠蔽する

例えば、XORを使ってキーを2つのバイト配列に分割することができます。

key = key1 XOR key2

と同じバイト長でkey1を作成すると key と同じバイト長で作成すると、(完全に)ランダムなバイト値を使用することができ、その上で key2 :

key1[n] = crypto_grade_random_number(0..255)
key2[n] = key[n] XOR key1[n]

これをビルド環境で行うことで、ビルド時にのみ格納される key1key2 を追加してください。

バイナリの保護

もう一つの方法は、バイナリを保護するためのツールを使用することです。 たとえば、バイナリが難読化され、その上で実行される仮想マシンを起動することを確認できるセキュリティ ツールがいくつか存在します。 これは、デバッグを困難にし、多くの商用グレードの安全なアプリケーション (残念ながら、マルウェア) を保護する一般的な方法です。

最も優れたツールの 1 つが テミーダ で、これはバイナリを保護する素晴らしい仕事をします。 これは、リバースエンジニアリングから保護するために、Spotify のような有名なプログラムでよく使用されています。 また、OllyDbg や Ida Pro などのプログラムでのデバッグを防止する機能も備えています。

また、より大きなリストもあります。 バイナリを保護するためのツール .

中には無料のものもあります。

パスワード照合

パスワードとソルトのハッシュ化について議論した人がいます。

もし、ユーザーが提出したある種のパスワードと照合するためにキーを保存する必要があるなら、ユーザー名、パスワード、ソルトを組み合わせた一方向ハッシュ関数を使用することが望ましいです。 しかし、この問題は、アプリケーションがソルトを知らなければ、一方向ハッシュを実行し、結果のハッシュを比較することができないことです。 そのため、アプリケーションのどこかにソルトを保存しておく必要があります。しかし、@Edward が以下のコメントで指摘しているように、これは例えばレインボーテーブルを使った辞書攻撃から効果的に保護することができます。

最後に、上記のすべてのテクニックを組み合わせて使うことができます。