7

私が取り組んでいるプログラムに対する機能要求の 1 つは、ユーザーが入力した資格情報のリストを保存して、それらを共有できるようにすることです。この要求に影響を与えた特定のユース ケースは、不安定な WAN によって接続されたかなり優れた LAN で構成された大規模な企業ネットワークで私たちのプログラムを使用することでした。WAN がダウンしたときにプログラムを打ち負かす代わりに、厳重に保護された管理者資格情報を含む「構成」ファイルを送信し、各 LAN で実行し、結果を圧縮して電子メールで送信するというアイデアでした。戻る。

うん。

私の最初の本能は、この要求を嘲笑することです-パスワードを保存しますか? 本当?確かに、会社のネットワーク部門は、彼らが持っているWAN製品を試して販売することを望んでいます-しかし、私が資格情報を使用するクラスの1つがSecureStringを取ることができることがわかりました.人々の労力を節約する方法。それは私に疑問に思いました:

暗号化された SecureString を保存して、機密データをファイルに保存し、別の場所で開くことはできますか?

スタックオーバーフロー、どう思いますか?

4

7 に答える 7

5

SecureString には保存のサポートはありません。これは、メモリ内の管理された文字列を保護するためのメカニズムとして意図されており、管理されていない API とのインターフェイスにのみ使用されます。パスワードが System.String インスタンスに格納されている場合、System.String の性質によりセキュリティが低下します。ガベージ コレクションとインターンが存在すると、パスワードが必要以上に長くメモリに保持されます。また、.NET 用の優れたデバッグ ツールが豊富にあるため、有効期間が長くなくても、リフレクションまたは別の .NET API を介して文字列にアクセスする方がはるかに簡単です。

パスワードをディスクに保存しようとすると、セキュリティがかなり損なわれます。誰かがマシンに物理的にアクセスしたり、管理者レベルのリモート アクセスを持っている場合、あなたができる最善の方法はそれをより難しくすることですが、決して不可能ではありません。暗号化 API を使用して安全な場所に保存し、アクセス権を構成します。

それはさておき、Merus、システム全体を改善することをお勧めします。なぜなら、あなたが説明しているようなユースケースでは(私が理解していると仮定して)、実際のパスワードよりもハッシュを保存する方がよいからです。

于 2008-09-29T07:06:37.947 に答える
4

パスワードハッシュの比較を見たいと思うかもしれません。
ユーザー名とおそらく他の定数で作られたソルトの後に文字列が続きます。次に、それを SHA1* などのハッシュ アルゴリズムに渡します。
例えば、

using System.Security.Cryptography;

public byte[] GetPasswordHash(string username, string password, string salt)
{
    // get salted byte[] buffer, containing username, password and some (constant) salt
    byte[] buffer;
    using (MemoryStream stream = new MemoryStream())
    using (StreamWriter writer = new StreamWriter(stream))
    {
        writer.Write(salt);
        writer.Write(username);
        writer.Write(password);
        writer.Flush();

        buffer = stream.ToArray();
    }

    // create a hash
    SHA1 sha1 = SHA1.Create();
    return sha1.ComputeHash(buffer);
}

次に、 の結果を と比較しGetPasswordHash(username, expectedPassword, salt)ますGetPasswordHash(username, givenPassword, salt)
ユーザー名とパスワードを使用して独自のユーザー リストを実装する場合は、ハッシュ ( GetPasswordHash(username, givenPassword, salt)) のみを保存し、保存したハッシュと比較することを検討してください。

于 2008-11-25T15:23:05.977 に答える
3

SecureString の暗号化されたバイトを保存する場合、これは機能しません。SecureString のキーはユーザーとプロセスに関連付けられています。別のプロセスで、または別のユーザーのためにそれらのバイトを読み取ると、文字列を解読する方法がありません。

于 2008-09-29T06:45:07.423 に答える
3

これは、メモリ内に存在することが保証されている SecureString のポイントを無効にします。したがって、ファイルに保存する場合は、「安全」ではないため、通常の文字列として保存することもできます。

于 2008-09-29T06:47:12.347 に答える
1

IsolatedStorageFileStream クラスを見てみることをお勧めします。アセンブリのみがアクセスできるファイル データを書き込んで保存する方法を指定します。

ただし、SecureStringを使用できるとは思いません。

于 2008-09-29T06:46:37.217 に答える
1

SecureString はシリアル化できないため、提供されている一部のシリアライザー (バイナリ、XML など) で保存することはできません。

また、securestring オブジェクトから「Password」プロパティなどにアクセスすることはできません。そのようなことはありません。これを行うには、マーシャリングと少しの配管を使用する必要があります。ユーザー資格情報をどこかに保存したい場合は、自分で暗号化することをお勧めします。これにより、後の開発が容易になります。SecureString アプローチを評価した後、自分で何かを実装することにしましたが、これらは私の 2 セントにすぎません。

于 2008-09-29T06:47:12.143 に答える
0

ここで述べたSecureStringように、このシナリオで使用する最良の方法ではありません。

ユーザーの資格情報を共有する必要がある場合は、おそらくユーザー名ハッシュ + ソルト化されたパスワードを共有するので、安全であり、内容ではなくパスワードの表現のみを共有します。

これを行う簡単な方法は、たとえば、BCryt ライブラリ(その .NET 表現がある場所) を使用し、共有する準備ができているテーブルでユーザー名とパスワードの表現をホストするだけです。

これはあなたがそれを使用する方法です:

StringBuilder sb = new StringBuilder();

// run ADO.NET / Entity Framework / etc and query your DB with something like:
"SELECT user_id, username, password FROM [TblUsers];"

// loop through the results

sb.AppendFormat(
       "INSERT INTO [TblSharedUsers] SELECT '{0}','{1}','{2}'",            
           dr["id"], dr["username"],
           BCrypt.HashPassword(dr["password"], BCrypt.GenerateSalt(12));
       );

// then run sb.ToSTring() agains your db

クライアント側では、から読み取り、次のようにユーザーパスワードを確認する新しいパスワードを作成できます (ネットワークがIoCDIAuthenticationProviderを使用して利用できない場合に簡単に変更できます)。TblSharedUsers

string userPassword = Request["password"];

"SELECT id, password FROM [TblSharedUsers] WHERE username = @usr;"

if( BCrypt.CheckPassword(userPassword, dr["password"]) )
    // User can log in
else
    // Credentials are invalid

これが同じ問題を抱えている人に役立つことを願っています。

于 2011-09-07T06:53:50.660 に答える