1

「convertfrom-securestring」を介してpowershellで作成され、ファイルに保存された暗号化された標準文字列があります。後で、この暗号化された文字列を C# アプリで (同じユーザー ID で同じマシン上で) 読み取りました。この暗号化された文字列を securestring オブジェクトに変換したいと考えています。PowerShell では、「convertto-securestring」を使用してこれを行うことができます。c#でこれを安全に行うにはどうすればよいですか?

私はこの回答 ( ConvertTo-SecureString を使用するにはどうすればよいですか)を認識していますが、暗号化された文字列が既知のキーで作成されていることを前提としています。これは、暗号化された文字列がキーなしで作成された場合とは異なります (したがって、それが構築されたユーザー ID とマシンに関連付けられています)。

上記の質問のコメントでは、キーが提供されない場合に Windows Data Protection API (DPAPI) が使用されることを示す Microsoft のドキュメントが引用されていることにも注意してください。この記事 ( https://msdn.microsoft.com/en-us/library/ms229741(v=vs.110).aspx ) は DPAPI の使用方法を示していますが、残念ながら Microsoft の記事で指定されている方法で使用すると、その結果、文字列オブジェクト内で文字列がクリアテキストになるため (処分に対して制御することはできません)、示されている方法でそれを使用することは安全ではありません。

実際、これは事実上、これ ( PowerShell で暗号化された C# で文字列を復号化する方法) とConvertTo-SecureString を使用するにはどうすればよいかの質問の組み合わせです。

記録のために、このコードは機能しますが、復号化された文字列をバイト配列と文字配列に保存する際の問題が何であるかはわかりません。

public static System.Security.SecureString MakeSecurityString(string pwd)
{
    int lngth = pwd.Length / 2;
    byte[] encrypted = new byte[lngth];
    for (int i = 0; i < lngth; ++i)
    {
        encrypted[i] = byte.Parse(pwd.Substring(2 * i, 2), System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture);
    }

    byte[] decrypted = System.Security.Cryptography.ProtectedData.Unprotect(encrypted, (byte[])null, System.Security.Cryptography.DataProtectionScope.CurrentUser);
    var chars = System.Text.UnicodeEncoding.Unicode.GetChars(decrypted);
    for(int i=0; i<decrypted.Length; ++i)
    {
        decrypted[i]=0;
    }
    var secureString = new System.Security.SecureString();
    for (int i = 0; i < chars.Length; ++i)
    {
        secureString.AppendChar(chars[i]);
        chars[i] = '\0';
    }

    return secureString;
}

上記のコードは安全だと思いますが、パスワードが byte-arraydecryptedと char-arrayの平文であるという短い瞬間を除いてchars、少なくともパスワードがぶらぶらしないように、これらをできるだけ早くゼロにしますがルーチンを終了した後のメモリ内。これは、 Oguz secureString.AppendCharOzgu が以下で指摘したようにsecureString、文字列を内部で復号化してから再暗号化する必要があることを意味します。これは安全に行われていると推測できます。誰かが上記のコードのセキュリティの問題についてコメントできますか?

編集: 以下のコードは への複数回の呼び出しを回避しますがsecureString.AppendChar、「安全でない」として実行する必要があることに注意してください。

        SecureString secureString;
        fixed (char* pChars = chars)
        {
            secureString = new SecureString(pChars, chars.Length);
        }
        for (int i = 0; i < chars.Length; ++i)
        {
            chars[i] = '\0';
        }
        return secureString;

以下のIndigoのコメントのリンクは、これがWindows上の.NETフレームワークでのみ安全であることを明確にしていることにも注意してください。

4

1 に答える 1

0

これを行うためのネイティブ C# メソッドがあるかどうかはわかりませんが、そうでない場合は、いつでも実行空間を使用して PowerShell パイプラインを実行し、コマンドレットを使用する方法に戻ることができます。

実行空間を開いたままにしておくと、繰り返しの実行がかなり速くなります。

于 2015-11-23T21:13:20.293 に答える