パスワードを(できればテキスト)ファイルに保存して暗号化する必要があります。後で復号化できるようにする必要があります。パスワードは私が使用している別のサービス用であり、クリアテキスト(SSL経由)で送信する必要があります。これは私が変更できるものではありません。この分野のベストプラクティスは何ですか?悪意のあるユーザーからパスワードをある程度保護するにはどうすればよいですか?
私のプラットフォームは、C#/。NET3.5を使用するWinFormsです。
ありがとう。
ユーザーのマシンにあるパスワードを暗号化すると、ユーザーは(おそらく)パスワードを見つけて使用できるようになると思いますか?もしそうなら、あなたは基本的に困惑しています-あなたが何をしても、それはユーザードメインにあるので、彼らはそれを取得して暗号化を理解し、暗号化のパスワードを取得することができます(Reflectorを使用することを忘れないでください-そしてそれはクローンです-ほとんどの人の手の届かないところにありません)そしてそれを解読すれば彼らはそれを持っています。要するに、あなたがしているのは、パスワードを保護するのではなく、難読化することだけです。
私がお勧めするのは、実際にはユーザーの制御から外すことです。たとえば、クライアントと通信し、要求されたときにパスワードを安全に返すWebサービスを設定します。これにより、将来必要に応じてパスワードを変更できるだけでなく、正当なユーザーを検証する方法も提供されます。
なぜパスワードを解読する必要があるのですか?通常、パスワードのソルトハッシュが保存され、比較されます。パスワードを暗号化/復号化すると、パスワードは再びプレーンテキストになり、これは危険です。一部のユーザーが同じパスワードを使用している場合は、ハッシュが重複しないようにハッシュをソルトする必要があります。ソルトの場合は、ユーザー名を使用できます。
HashAlgorithm hash = new SHA256Managed();
string password = "12345";
string salt = "UserName";
// compute hash of the password prefixing password with the salt
byte[] plainTextBytes = Encoding.UTF8.GetBytes(salt + password);
byte[] hashBytes = hash.ComputeHash(plainTextBytes);
string hashValue = Convert.ToBase64String(hashBytes);
パスワードのソルトハッシュを計算して、ファイル内に保存できます。認証中に、ユーザーエントリからハッシュを再度計算し、このハッシュを保存されているパスワードハッシュと比較します。ハッシュからプレーンテキストを取得することは非常に難しいはずなので(不可能ではなく、常に時間の問題です)、パスワードは再びプレーンテキストとして読み取られないように保護されています。
ヒント:暗号化されていないパスワードを保存または送信しないでください。新しいパスワードを取得した場合、暗号化はできるだけ早く行われます。
System.Security Assemblyの System.Security.Cryptography.ProtectedData は、いくつかのWindows APIを使用して、自分だけが知っているパスワードでデータを暗号化します。
これを使用する可能性のあるものの1つは、パスワードを必要とする操作を実際に実行するWindowsサービスを使用することです。ユーザーがリモート操作またはWCFを介してサービスへの呼び出しと対話するアプリケーション。サービスがDataProtectionScope.CurrentUserを使用し、サービスユーザーがログオンユーザーと異なる限り、パスワードはかなり安全である必要があります。
もちろん、これは、ユーザーがサービスを変更したり、サービスのユーザーとしてプログラムを実行したりできない制限付きユーザーとして実行されていることを前提としています。
WinFormsと.Netを使用しているため、難読化されていても、コードはMSILに表示され、復号化コードが表示されます。
パスワードを誰から隠そうとしていますか?アプリのユーザーはパスワードを知らないはずですか?
ユーザー検証を行う必要があると思います。復号化のキーを別のデータベースに配置し、認証が必要なものを取得するための他のメカニズムを提供したいと思います。そうすれば、winformsアプリから復号化コードを取得できます。
また、暗号化復号化キーを定期的に変更し、データベース内のすべてのパスワードを更新するために実行される別のサービスをお勧めします。
ユーザーが入力したパスワードを保存するために、このようなものを実装しました。暗号化された結果をbase64でエンコードされた文字列に変換したので、アプリケーションのユーザー設定に簡単に保存できました。
あなたの質問から、あなたの悪意のあるユーザーが実際にあなたのアプリケーションを使用しているように思われるので、これは難読化を提供するだけです。 Reflectorを使用してもキーは表示されませんが、デバッガーではプレーンテキストが表示されます。
static byte[] entropy = { 65, 34, 87, 33 };
public string Password
{
get
{
if (this.EncryptedPassword == string.Empty)
{
return string.Empty;
}
var encrypted = Convert.FromBase64String(this.EncryptedPassword);
var data = ProtectedData.Unprotect(encrypted, entropy, DataProtectionScope.CurrentUser);
var password = Encoding.UTF8.GetString(data);
return password;
}
set
{
if (value == string.Empty)
{
this.EncryptedPassword = string.Empty;
return;
}
var data = Encoding.UTF8.GetBytes(value);
var encrypted = ProtectedData.Protect(data, entropy, DataProtectionScope.CurrentUser);
var stored = Convert.ToBase64String(encrypted);
this.EncryptedPassword = stored;
}
}
mustをテキストファイルに保存する必要がある場合は、AESで暗号化されます。
AESは、C#ではRijndaelとしてよく知られています。
http://www.obviex.com/samples/Encryption.aspx
レジストリは、アクセスするマシンの他のユーザーを保護するため、より適切な場所になります。
それでも、ユーザーがアクセスできる場所に保存するのは最善ではありません。それでも、適切な開発者がアプリをリフレクターにロードしてキーを見つけることができるのは危険です。
または、他の誰かが提案したSystem.Security.Cryptography.ProtectedDataがあります。
マシンでできる最善のことは、証明書を作成し、それをマシンのキーストアにロードしてロックダウンした状態で暗号化/復号化することです。 (それでも、コードに含まれている証明書のパスワードを処理する必要があります)
パスワードをコードの一部として保存しないでください。逆コンパイルと隠すことによるセキュリティへの依存の問題は別として、パスワードを変更した場合は、アプリケーションを再コンパイルして再配布する必要があります。
パスワードは、Webサービスとして、またはアプリケーションがアクセスできるデータベースに保存します。あなたはウェブを介してサービスと通信しているので、結局のところ接続されます。
最も重要なことの1つは、ファイルのアクセス許可です。コンテンツが暗号化されている場合でも、ファイルへのアクセスが必要なプロセスのみがコンテンツを読み取れるようにする必要があります。
パスワードは暗号化されていない形式でネットワーク経由で送信する必要があるため、100%保護するためにできることは何もありません。
ローカルに保存する必要がある場合はAESで十分ですが、disasms、ネットワークスニファなどについて話すことは、同じことがanyプログラムで実行できるため、特に良い反論ではありません(確かに、ASMはより難しいです) CILですが、そのマイナーポイント)。
このようなパスワード保護は、専門家によるデコードを防ぐのではなく、カジュアルなピックアップを防ぐのに十分です。