WPF 的PasswordBox 返回一个SecureString,它对窥探者隐藏密码。
问题是你最终必须获得密码的值,而我在网上找到的建议都涉及将值复制到字符串中,这会让你回到窥探者的问题。
IntPtr bstr = Marshal.SecureStringToBSTR(secureString);
string password = Marshal.PtrToStringBSTR(bstr);
Marshal.FreeBSTR(bstr);
但如果您认真考虑一下,您实际上并不需要该值作为字符串。我的意思是,你用密码做什么?对它进行散列,然后将结果与保存的散列进行比较,看看它们是否相同。
换句话说,您不需要将 SecureString 转换为字符串,只需能够迭代字符串中的各个字符即可。
But how?
如何在 C# 中循环 BSTR 中的各个字符,而不将其转换为托管字符串?
编辑:解决方案,以防链接消失:
Marshall 类提供了可以从 IntPtr 中按给定偏移量提取单个字节或整数的方法。 BSTR 对象包含一个 16 位字符数组,以两个空字节终止。所以你可以通过循环访问它们:
byte b = 1;
int i = 0;
while ((char)b != '\0')
{
b = Marshal.ReadByte(bstr, i);
// ...
i += 2;
}
(我不关心那个流程控制。我会使用 do...while,而不是用虚拟值预填充 b,或者我会使用 for(;;) 循环,并带有内部中断,或者我会循环长度,我在下面解释如何获得它。)
另外,我可能会使用:
short b = Marshal.ReadInt16(bstr, i);
读取整个 unicode 字符,而不是仅读取每个字符的低字节。
您可以通过以下方式获取 BSTR 的长度:
int len = Marshal.ReadInt32(bstr, -4);
这是字节数,不包括空值,而不是字符数。
另外 - 使用:
Marshal.ZeroFreeBSTR(bstr);