WPFのPasswordBoxは、パスワードをスヌーパーから隠すSecureStringを返します。
問題は、最終的にパスワードの値を取得する必要があることです。ネット上で私が見つけた提案はすべて、値を文字列にコピーすることで、スヌーパーの問題に戻ります。
IntPtr bstr = Marshal.SecureStringToBSTR(secureString);
string password = Marshal.PtrToStringBSTR(bstr);
Marshal.FreeBSTR(bstr);
しかし、実際に考えてみると、文字列としての値は実際には必要ありません。つまり、パスワードで何をしますか?それをハッシュしてから、結果を保存されたハッシュと比較し、それらが同じであるかどうかを確認します。
つまり、SecureStringを文字列に変換する必要はなく、文字列内の個々の文字を反復処理できる必要があります。
しかし、どのように?
管理された文字列に変換せずに、C#でBSTRの個々の文字をループするにはどうすればよいですか?
編集:リンクが消えた場合の解決策:
Marshallクラスは、指定されたオフセットでIntPtrから個々のバイトまたはintを抽出できるメソッドを提供します。BSTRオブジェクトには、2つのヌルバイトで終了する16ビット文字の配列が含まれています。したがって、ループすることでそれらにアクセスできます。
byte b = 1;
int i = 0;
while ((char)b != '\0')
{
b = Marshal.ReadByte(bstr, i);
// ...
i += 2;
}
(私はそのフロー制御を気にしません。ダミー値をbに事前入力するのではなく、do ... whileを使用したか、内部ブレークを使用してfor(;;)ループを使用しました。または、長さをループしていると思います。これについては、以下で説明します。)
また、私はおそらく使用します:
short b = Marshal.ReadInt16(bstr, i);
それぞれの下位バイトだけでなく、Unicode文字全体を読み取ります。
BSTRの長さは、次の方法で取得できます。
int len = Marshal.ReadInt32(bstr, -4);
これは、文字数ではなく、ヌルを含まないバイト数です。
また-使用:
Marshal.ZeroFreeBSTR(bstr);