在C#中从.NET SecureString读取单个字符?

在C#中从.NET SecureString读取单个字符?,c#,bstr,securestring,C#,Bstr,Securestring,WPF的PasswordBox返回一个SecureString,它对窥探者隐藏密码 IntPtr bstr = Marshal.SecureStringToBSTR(secureString); string password = Marshal.PtrToStringBSTR(bstr); Marshal.FreeBSTR(bstr); 问题是你最终必须得到密码的值,我在网上找到的建议都涉及到将值复制到字符串中,这让你回到窥探者的问题上来 IntPtr bstr = Marshal.Secu

WPF的PasswordBox返回一个SecureString,它对窥探者隐藏密码

IntPtr bstr = Marshal.SecureStringToBSTR(secureString);
string password = Marshal.PtrToStringBSTR(bstr);
Marshal.FreeBSTR(bstr);
问题是你最终必须得到密码的值,我在网上找到的建议都涉及到将值复制到字符串中,这让你回到窥探者的问题上来

IntPtr bstr = Marshal.SecureStringToBSTR(secureString);
string password = Marshal.PtrToStringBSTR(bstr);
Marshal.FreeBSTR(bstr);
但是如果你真的想一想,你并不真的需要这个值,作为一个字符串。我是说,你用密码做什么?对其进行散列,然后将结果与保存的散列进行比较,看看它们是否相同

换句话说,您不需要将SecureString转换为字符串,只需要能够迭代字符串中的各个字符

但是怎么做呢

如何在不将BSTR转换为托管字符串的情况下,在C#中循环BSTR中的各个字符

编辑:链接消失时的解决方案:

Marshall类提供的方法可以在给定偏移量下从IntPtr提取单个字节或INT。BSTR对象包含一个由16位字符组成的数组,以两个空字节结尾。因此,您可以通过循环访问它们:

字节b=1;
int i=0;
而((char)b!='\0')
{
b=封送处理读取字节(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);


此链接显示如何使用Marshal.SecureStringToBSTR(secretString)并将其分配给指针,并更新指针以循环字符。

尝试类似的操作我将lc在链接中的VB代码示例转换为C 希望这能帮助你开始

Char[] input = "Super Secret String".ToCharArray();
SecureString secret = new SecureString();

for (int idx = 0; idx <= input.Length - 1; idx++) {
    secret.AppendChar(FileSystem.input(idx));
}
SecurePassword.MakeReadOnly();

IntPtr pBStr = Marshal.SecureStringToBSTR(secret);

string output = Marshal.PtrToStringBSTR(pBStr);
Marshal.FreeBSTR(pBStr);

SHA512 sha = new SHA512Managed();
byte[] result = sha.ComputeHash(Encoding.UTF8.GetBytes(output));
Char[]input=“Super Secret String”.ToCharArray();
SecureString secret=新SecureString();
对于(intidx=0;idx这对我来说很有效:

    static char GetChar(SecureString value, int idx)
    {
        IntPtr bstr = Marshal.SecureStringToBSTR(value);
        try
        {
            // Index in 2-byte (char) chunks
            //TODO: Some range validation might be good.
            return (char)Marshal.ReadByte(bstr, idx * 2);
        }
        finally
        {
            Marshal.FreeBSTR(bstr);
        }
    }

你试过for循环或foreach循环吗?他是用C语言做的,我想这个例子并没有达到我不希望的效果,它将字符串复制到一个托管字符串中。这不是将明文密码留在内存中的值
输出
?这里的关键是不要在托管环境中将值作为字符串读回NT。请参见为什么。也推荐使用<代码> MARHALL。ZeroFreeBSTR < /C> >以确保明文密码从非托管内存ASAP.PoT中被清除。我不认为我或多或少关注于从VB向C See等提供一个工作版本。