title: Is it possible to safely get a SecureString value from VB .NET?
body: <p>I've always felt like SecureString was a little odd, but assumed most of my issues with it were due to security problems I don't understand.  Today I decided to sit down and teach myself about it, but I've hit what seems like a fatal snag.</p>
  
  <p>The scenario I envision is "user enters password into text box, that password is hashed and compared to a stored hash".  At first I was worried that the text box contained the string, but then I realized you could roll a custom text box that uses SecureString as its store.  Cool.  It's the "that password is hashed and compared..." part that is giving me trouble.  </p>
  
  <p>My first hack at the problem in VB .NET was naive and wrong:</p>
  
  <pre><code>Dim passwordHandle As IntPtr
  Dim insecurePassword As String = Nothing
  Try
      passwordHandle = Marshal.SecureStringToBSTR(_password)
      insecurePassword = Marshal.PtrToStringBSTR(passwordHandle)
  Catch ex As Exception
  
  Finally
      If passwordHandle &lt;&gt; IntPtr.Zero Then
          Marshal.ZeroFreeBSTR(passwordHandle)
      End If
  End Try
  
  If insecurePassword &lt;&gt; Nothing Then
      ' Do hash and comparison
  End If
  </code></pre>
  
  <p>This just stuffs the password into a regular string and defeats the purpose of using SecureString in the first place.  So I kept searching and found <a href="http://dotnet.org.za/markn/archive/2008/10/04/handling-passwords.aspx" rel="nofollow noreferrer">a blog post</a> that solves the problem nicely in C#: the string is made into a BSTR, copied into a pinned string, then both the BSTR and pinned string are zeroed after use.  This seems like a much better idea because it minimizes the amount of time that the insecure string is in memory.  However, it doesn't look like there's a way to pull this off in VB .NET.  C# is using its unsafe code feature to do pointer manipulations, but VB .NET cannot do this.  I had a look at Marhsall.Copy(), but it looks like it's oriented towards arrays.  I thought about trying to cast the IntPtr variables for the object and BSTR to Strings, but that still left me using a method like String.Replace(), which will create a new string.</p>
  
  <p>Is it not possible to do this from VB .NET at all, or is there something I'm missing?</p>
  
  <p><em>edit</em>
  I'm accepting AMissico's answer with only slight reservations. The Marshal.ReadByte() method will copy a byte from unmanaged memory and create a byte in unmanaged memory. This produces the small chance that an attacker could find the individual characters of the password. I think that's far less than the odds of finding an entire string, but the C# in the (apparently defunct) article I referenced was able to use unsafe code to avoid this neatly. The thought process was it used GCHandle to pin a string in memory, then used unsafe code to get around the immutability of .NET strings. Clever trick that seems impossible in VB .NET. I'll try to come back with the C# code itself.</p>