【问题标题】:Reading single chars from a .NET SecureString in C#?从 C# 中的 .NET SecureString 读取单个字符?
【发布时间】:2012-07-12 19:07:53
【问题描述】:

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

问题是你最终必须得到密码的值,而我在网上找到的建议都涉及将值复制到一个字符串中,这让你回到了窥探者的问题。

IntPtr bstr = Marshal.SecureStringToBSTR(secureString);
string password = Marshal.PtrToStringBSTR(bstr);
Marshal.FreeBSTR(bstr);

但如果你真的考虑一下,你并不真的需要这个值,作为一个字符串。我的意思是,你用密码做什么?您对其进行哈希处理,然后将结果与保存的哈希值进行比较,看看它们是否相同。

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

但是怎么做呢?

如何在 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);

【问题讨论】:

  • 你试过for循环还是foreach循环..???
  • 他在 C# 中这样做我假设不是 VB lc
  • 该示例完全符合我的要求,它将字符串复制到托管字符串中。

标签: c# bstr securestring


【解决方案1】:

http://weblogs.asp.net/pglavich/archive/2005/08/15/422525.aspx

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

【讨论】:

    【解决方案2】:

    这对我有用:

        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);
            }
        }
    

    【讨论】:

      【解决方案3】:

      尝试这样的事情我为您将 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));
      

      【讨论】:

      • 这不是将明文密码留在内存中的值output吗?这里的关键是不要在托管环境中将值作为字符串读回。请参阅msdn.microsoft.com/en-us/library/system.security.securestring 了解原因。此外,建议使用Marshal.ZeroFreeBSTR 以确保尽快从非托管内存中清除明文密码。
      • 点得很好。我不认为我或多或少专注于为他提供从 VB 到 C# Equiv 的工作版本
      猜你喜欢
      • 2017-04-01
      • 1970-01-01
      • 2013-01-03
      • 2021-07-01
      • 1970-01-01
      • 2012-02-28
      • 2013-04-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多