c# wpf encryption securestring

SecureString a Byte[] C#



wpf encryption (3)

Modifiqué de la respuesta original para manejar unicode

IntPtr unmanagedBytes = Marshal.SecureStringToGlobalAllocUnicode(password); byte[] bValue = null; try { byte* byteArray = (byte*)unmanagedBytes.GetPointer(); // Find the end of the string byte* pEnd = byteArray; char c=''/0''; do { byte b1=*pEnd++; byte b2=*pEnd++; c = ''/0''; c= (char)(b1 << 8); c += (char)b2; }while (c != ''/0''); // Length is effectively the difference here (note we''re 2 past end) int length = (int)((pEnd - byteArray) - 2); bValue = new byte[length]; for (int i=0;i<length;++i) { // Work with data in byte array as necessary, via pointers, here bValue[i] = *(byteArray + i); } } finally { // This will completely remove the data from memory Marshal.ZeroFreeGlobalAllocUnicode(unmanagedBytes); }

¿Cómo obtendría un byte[] equivalente a un SecureString (que obtengo de un PasswordBox )?

Mi objetivo es escribir estos bytes usando un CryptoStream en un archivo, y el método Write de esa clase toma una entrada byte[] , por lo que quiero convertir SecureString en el byte[] para que pueda usarlo con CryptoStream .

EDITAR: no quiero usar string ya que se SecureString el punto de tener un SecureString


Según esto, http://www.microsoft.com/indonesia/msdn/credmgmt.aspx , puede convertirlo en una cadena C # estándar y luego convertirlo en una matriz de bytes:

static string SecureStringToString( SecureString value ) { string s ; IntPtr p = Marshal.SecureStringToBSTR( value ); try { s = Marshal.PtrToStringBSTR( p ) ; } finally { Marshal.FreeBSTR( p ) ; } return s ; }

o según esta respuesta, ¿Cómo convertir SecureString a System.String? , puede usar Marshal.ReadByte y Marshal.ReadInt16 en IntPtr para obtener lo que necesita.


Suponiendo que desea utilizar la matriz de bytes y deshacerse de ella tan pronto como haya terminado, debe encapsular toda la operación para que se limpie después de sí misma:

public static T Process<T>(this SecureString src, Func<byte[], T> func) { IntPtr bstr = IntPtr.Zero; byte[] workArray = null; GCHandle handle = GCHandle.Alloc(workArray, GCHandleType.Pinned); try { /*** PLAINTEXT EXPOSURE BEGINS HERE ***/ bstr = Marshal.SecureStringToBSTR(src); unsafe { byte* bstrBytes = (byte*)bstr; workArray = new byte[src.Length * 2]; for (int i = 0; i < workArray.Length; i++) workArray[i] = *bstrBytes++; } return func(workArray); } finally { if (workArray != null) for (int i = 0; i < workArray.Length; i++) workArray[i] = 0; handle.Free(); if (bstr != IntPtr.Zero) Marshal.ZeroFreeBSTR(bstr); /*** PLAINTEXT EXPOSURE ENDS HERE ***/ } }

Y así es como se ve un caso de uso:

private byte[] GetHash(SecureString password) { using (var h = new SHA256Cng()) // or your hash of choice { return password.Process(h.ComputeHash); } }

Sin rumores, sin problemas, sin texto claro dejado flotando en la memoria.

Tenga en cuenta que la matriz de bytes que se pasa a func() contiene la representación en bruto Unicode del texto plano, lo que no debería ser un problema para la mayoría de las aplicaciones criptográficas.