web-dev-qa-db-ja.com

コード内の機密データを保護するための最良の方法は何ですか?

コードを逆コンパイルから保護する方法を検討していました。

ここには、コードを保護するための可能な方法として、難読化とコードパッキングについて説明している優れたスレッドがいくつかあります。ただし、どれも理想的ではなく、文字列メソッド/プロパティ名が使用されている場合、難読化はリフレクションでは機能しません。多くの人は、難読化の使用をまったく推奨していません。

だから私は現在、上記のどれにも行かないことに決めました。 ただしある種の暗号化が必要なコードの部分がありますたとえば、データベース接続文字列とIP、ログイン、パスワードは、メールアカウントデータと同じように、単純なconst stringとしてコード内に保存されます。

ASP.NETには、機密データを.configファイルに移動して暗号化するオプションがありますが、これにはサーバーキーが必要です。つまり、単一のコンピューターにリンクされている必要があります。私はそれについてあまり読んでいませんでしたが、デスクトップアプリケーションにも同様の何かが利用できると思います。しかし、アプリケーションがインストールされているanyコンピューターで動作するには、これが必要です。

そしてここに質問があります:逆コンパイルされたコードと一緒に読み取れないようにそのようなデータをエンコード/保護する方法はありますか?

21
net_prog

最初のアドバイスは、コードに機密性の高いものを直接決して保存しないことです。どんなに巧妙に難読化しようとしても、常にリバースエンジニアリングすることができます。

パスワードをいくつかの部分に分割し、コード内のさまざまな場所に配置し、一連の関数を実行してから最終的に使用するなどについて読んだことがあります...これにより困難になりますが、アプリケーションをいつでも監視できますデバッガーを使用すると、最終的には秘密情報を取得できるようになります。

私があなたのシナリオを正しく解釈すると、あなたが持っているのは、あるクライアントの構内に展開されるコードであり、あなたのコードはデータベースに接続され(私はクライアントの監督下にあると思います)、それに接続するにはパスワードが必要です。このパスワードはそのクライアントに認識されているため、クライアントからパスワードを隠そうとしても意味がありません。あなたdoが望んでいるのは、パスワードを知らないはずの人からのパスワードへのアクセスを制限することです。

これは通常、機密情報を非常に制限されたアクセス許可を持つ必要があるフォルダー内の別のファイルに配置することで実現します。アプリケーションと少数の選択したユーザーのみがアクセスできる必要があります。その後、アプリケーションは実行時に必要なときに情報にアクセスします。

さらに、個別のファイルを暗号化することは問題であることが判明します-そうすると、何らかの方法で再度保護する必要があるキーが含まれます-無限再帰が進行中です:)ファイルへのアクセスを保護することで十分なことがよくありますが、本当に可能な限り安全である必要がある場合、解決策はファイルにパスワードベースの暗号化を使用することです。ただし、ここでの考え方は、パスワードをシステムのさらに別の場所に保存するのではなく、帯域外情報(物理的な保管庫など)として保存し、アプリケーションの起動時にパスワードを入力することです。これにも問題があります。アプリケーションを(再)起動するには人の物理的な存在が必要ですが、アプリケーションが存在するマシンのRAM)からパスワードを取得できます。実行中です。しかし、それはおそらく、専用のハードウェアなしで実行できる最善の方法です。

パスワードベースの暗号化に代わるもう1つの優れた方法は、WindowsなどのOS固有の「パスワードボールト」に依存することです。 分離ストレージ これは、暗号化をまったく行わないこととパスワードを保持することの間のトレードオフのようなものです。帯域外。

19
emboss

これは暗号化の答えではありませんが、これを「保護」する1つの方法は、Webサービスを介してすべてのデータベース呼び出しを行うことです。次に、接続資格情報が安全なサーバーに保存され、クライアントはそこを介してすべての呼び出しを渡します。

再配布可能なものには機密情報は一切保存されていません...

11
Paddy

私は過去にこの問題に取り組み、問題に対処する3つの方法を考え出しましたが、どれも完璧かどうかはわかりません。

  1. 値を難読化または暗号化し、最高のものを期待します。もちろん、暗号化は、キーを残りのキーと一緒に配信する必要があるため、難読化のレベルが高くなります。
  2. 代わりに一方向の暗号化を使用して、キー自体の必要性を排除します。秘密鍵を使用して公開鍵を生成します。これは、ライセンスまたはパスワードの検証に使用できます。秘密鍵を使用してライセンスを生成しますが、公開鍵を使用してそれらを検証できます。または、秘密鍵を使用して、検証はできるが公開鍵を使用して元に戻すことはできないパスワードを生成します。
  3. ASP.NETで使用されるものと同様の独自のシステム固有のキー生成メカニズムを作成します。インストールまたはサイトごとに一意のキーを生成することにより、手順1で暗号化/難読化を元に戻す人の影響を制限できます。
5
BlueMonkMN

たくさんの方法がありますが、実際には、コードを本当に保護したい場合、唯一の解決策は「プロの」製品を使用することです:-)車輪の再発明を試みないでください。これらの製品には通常、文字列を暗号化するオプションがあります。本当の問題は別の問題です。プロの製品がなくても(プロの製品があったとしても)、エキスパートはブレークポイントを設定して、ライブラリメソッドに渡されたパラメーター(接続を開くパラメーターなど)を確認できます。さて...本当にコードの文字列を暗号化したいのなら、それはとても簡単です。しかし、それは役に立ちますか?番号。

さて、誰もこれを「答えではない」とマークしないように、簡単な暗号化/復号化コードを投稿します。

_// Generate key. You do it once and save the key in the code
var encryptorForGenerateKey = Aes.Create();
encryptorForGenerateKey.BlockSize = 128;
encryptorForGenerateKey.KeySize = 128;
encryptorForGenerateKey.GenerateKey();
encryptorForGenerateKey.GenerateIV();

var key = encryptorForGenerateKey.Key;
var iv = encryptorForGenerateKey.IV;

// Encrypt: this code doesn't need to be in the program. You create a console
// program to do it
var encryptor = Aes.Create();
var encryptorTransformer = encryptorForGenerateKey.CreateEncryptor(key, iv);

string str = "Hello world";
var bytes = Encoding.UTF8.GetBytes(str);
var encrypted = encryptorTransformer.TransformFinalBlock(bytes, 0, bytes.Length);
var encryptedString = Convert.ToBase64String(encrypted);

Console.WriteLine(encryptedString);

// Decrypt: this code needs to be in the program

var decryptor = Aes.Create();
var decryptorTransformer = decryptor.CreateDecryptor(key, iv);

byte[] encrypted2 = Convert.FromBase64String(encryptedString)

var result = decryptorTransformer.TransformFinalBlock(encrypted2, 0, encrypted2.Length);

var str2 = Encoding.UTF8.GetString(result);
_

このコードは明らかに安全ではありません。誰でもプログラムを逆コンパイルし、Console.WriteLine(str2)を追加して再コンパイルできます。

4
xanatos

もちろん、コンパイルする前に文字列を暗号化することはできますが、単純なdbまたはhttp urlを使用している場合は、コードでプレーンテキストで暗号化する必要があります。

この場合、実際の保護はありません。誰もが指定されたメソッドをリッスン(ブレークポイント)でき、呼び出されると、コードを実際に読まなくても何が起こっているかを確認できます。したがって、これに対する実際の保護はありません。また、ある時点で難読化を使用して、そのプレーンテキスト文字列で.NETメソッドを呼び出すと、誰でもそれを読むことができます。

たとえば、暗号化された文字列を格納するためのCOMまたはC++ dllを配置できます。管理されていないdllは逆コンパイルできませんが、専門家はもちろんdllの逆アセンブルを理解できます。そして、前に述べたように、いつかあなたはプレーンなデータを必要とするでしょう、そしてその瞬間、持続することができる保護はありません。

あなたができる唯一のことはあなたのアーキテクチャを変えることです。

たとえば、データベースがオンラインで、アプリケーションがクライアントアプリケーションの場合、Webサービスを使用して接続できます。そうすれば、ユーザーが実際に使用する必要のあるWebサービスのみを公開でき、ユーザーがSQLクエリを作成するリスクはありません。次に、クライアントではなくサーバーに保護ロジックを追加できます。

すべてがオフラインの場合、できることはあまりありません。単純な文字列暗号化を使用して生活を困難にすることはできますが、それが本当の保護になることは決してありません。

3

Lucasがコメントで指摘しているように、ピースが1つしかない場合は、アプリケーションを逆コンパイルする人は誰でもそれをリバースエンジニアリングして、データベースのパスワードを復号化できます。

資格情報の保存については、通常、アプリケーション構成ファイルに常に保存します。それを保護する必要がある場合は、SecureStringといくつかの暗号化を使用します。そして、これは、資格情報だけでなく、あらゆる種類の構成情報に対して機能する可能性があります。ここに構成ファイルの保護に関する本当に良い記事があります: 。NET app.configファイルのパスワードの暗号化

3
Ucodia

たぶん、web.configの暗号化についてもう少し読む必要があります http://learn.iis.net/page.aspx/141/using-encryption-to-protect-passwords/

そうでなければ、あなたができることはあまりありません。リフレクターツールを持っている人なら誰でもデータを開いて表示できるため、機密データをコードに保存することはできません。コードや変数をすべての人に表示しないようにする場合は、プライベートサーバー上に、データを受け入れ、魔法のように変換してクライアントに返すWebサービスを作成する必要があります。このようにして、データの投稿と取得の間のすべてが秘密にされます。

1
Erwin