Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# SecureString Question

Is there any way to get the value of a SecureString without comprising security? For example, in the code below as soon as you do PtrToStringBSTR the string is no longer secure because strings are immutable and garbage collection is non-deterministic for strings.

IntPtr ptr = Marshal.SecureStringToBSTR(SecureString object); string value = Marshal.PtrToStringBSTR(ptr); 

What if there were a way to get a char[] or byte[] of the unmanaged BSTR string? Would that mean garbage collection is more predictable (since you would be using a char[] or byte[] rather than a string? Is this assumption correct, and if so, how would you get back the char[] or byte[]?

like image 924
Taylor Leese Avatar asked Nov 25 '09 23:11

Taylor Leese


People also ask

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.

What do you mean by C?

" " C is a computer programming language. That means that you can use C to create lists of instructions for a computer to follow. C is one of thousands of programming languages currently in use.

What is C in coding language?

C is a powerful general-purpose programming language. It can be used to develop software like operating systems, databases, compilers, and so on. C programming is an excellent language to learn to program for beginners. Our C tutorials will guide you to learn C programming one step at a time.


2 Answers

Here's a class I've written especially for this purpose. Is it completely, 100% hackproof? No - there's very little you can do to make an application 100% safe, but this class goes about as far as you can to protect yourself if you need to convert a SecureString into a String.

Here's how you use the class:

using(SecureStringToStringMarshaler sm = new SecureStringToStringMarshaler(secureString)) {     // Use sm.String here.  While in the 'using' block, the string is accessible     // but pinned in memory.  When the 'using' block terminates, the string is zeroed     // out for security, and garbage collected as usual. } 

Here's the class

/// Copyright (C) 2010 Douglas Day /// All rights reserved. /// MIT-licensed: http://www.opensource.org/licenses/mit-license.php  using System; using System.Collections.Generic; using System.Text; using System.Security; using System.Runtime.InteropServices; using System.Runtime.CompilerServices;  namespace DDay.Base {     public class SecureStringToStringMarshaler : IDisposable     {         #region Private Fields          private string _String;         private SecureString _SecureString;         private GCHandle _GCH;          #endregion          #region Public Properties          public SecureString SecureString         {             get { return _SecureString; }             set             {                 _SecureString = value;                 UpdateStringValue();             }         }          public string String         {             get { return _String; }             protected set { _String = value; }         }           #endregion          #region Constructors          public SecureStringToStringMarshaler()         {         }          public SecureStringToStringMarshaler(SecureString ss)                 {             SecureString = ss;         }          #endregion          #region Private Methods          void UpdateStringValue()         {             Deallocate();              unsafe             {                 if (SecureString != null)                 {                     int length = SecureString.Length;                     String = new string('\0', length);                      _GCH = new GCHandle();                      // Create a CER (Contrained Execution Region)                     RuntimeHelpers.PrepareConstrainedRegions();                     try { }                     finally                     {                         // Pin our string, disallowing the garbage collector from                         // moving it around.                         _GCH = GCHandle.Alloc(String, GCHandleType.Pinned);                     }                      IntPtr stringPtr = IntPtr.Zero;                     RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(                         delegate                         {                             // Create a CER (Contrained Execution Region)                             RuntimeHelpers.PrepareConstrainedRegions();                             try { }                             finally                             {                                 stringPtr = Marshal.SecureStringToBSTR(SecureString);                             }                              // Copy the SecureString content to our pinned string                             char* pString = (char*)stringPtr;                             char* pInsecureString = (char*)_GCH.AddrOfPinnedObject();                             for (int index = 0; index < length; index++)                             {                                 pInsecureString[index] = pString[index];                             }                         },                         delegate                         {                             if (stringPtr != IntPtr.Zero)                             {                                 // Free the SecureString BSTR that was generated                                 Marshal.ZeroFreeBSTR(stringPtr);                             }                         },                         null);                 }             }         }          void Deallocate()         {                         if (_GCH.IsAllocated)             {                 unsafe                 {                     // Determine the length of the string                     int length = String.Length;                      // Zero each character of the string.                     char* pInsecureString = (char*)_GCH.AddrOfPinnedObject();                     for (int index = 0; index < length; index++)                     {                         pInsecureString[index] = '\0';                     }                      // Free the handle so the garbage collector                     // can dispose of it properly.                     _GCH.Free();                 }             }         }           #endregion          #region IDisposable Members          public void Dispose()         {             Deallocate();         }          #endregion     } } 

This code requires that you can compile unsafe code, but it works like a charm.

Regards,

-Doug

like image 60
Doug Avatar answered Sep 24 '22 13:09

Doug


This should help you: Marshaling SecureString Passwords to String

From the article, the key points are:

  • Pin the string in memory.
  • Use managed pointers to mutate the System.String.
  • Use the strong guarantees of the ExecuteCodeWithGuaranteedCleanup method.
like image 26
Mark Byers Avatar answered Sep 24 '22 13:09

Mark Byers