Todas las reservas sobre su destrinca SecureString mediante la creación de un System.String salir de ella a un lado , ¿cómo se puede hacer esto?
¿Cómo puedo convertir un System.Security.SecureString ordinario en System.String?
Estoy seguro de que muchos de ustedes que están familiarizados con SecureString responderán que uno nunca debe transformar un SecureString en una cadena .NET ordinaria porque elimina todas las protecciones de seguridad. Yo sé . Pero en este momento mi programa hace todo con cadenas normales de todos modos, y yo estoy tratando de mejorar su seguridad y aunque voy a estar usando una API que devuelve un SecureString a mi Soy no tratando de utilizar eso para aumentar mi seguridad.
Soy consciente de Marshal.SecureStringToBSTR, pero no sé cómo tomar ese BSTR y hacer un System.String fuera de él.
Para aquellos que pueden exigir saber por qué querría hacer esto, bueno, estoy tomando una contraseña de un usuario y la envío como un formulario html POST para registrar al usuario en un sitio web. Entonces ... esto realmente tiene que hacerse con buffers administrados y sin cifrar. Si incluso pudiera obtener acceso al búfer no administrado y no cifrado, imagino que podría escribir byte por byte en la transmisión de la red y espero que eso mantenga la contraseña segura todo el tiempo. Espero una respuesta al menos a uno de estos escenarios.
fuente
StopWatch
ySecureStringToString
tomó 4.6sec para funcionar. Es lento para mí. ¿Alguien tiene el mismo tiempo o algo más rápido?Database.GetConnectionString()
código en tu código para obtener mi secureString, que fue la parte malvada que tardó casi 5 segundos (¡y sí, debería investigarlo! :) Tu código tardó .00 mili segundos en mi cronómetro, así que es todo bien. Gracias por señalarme en la dirección correcta.Obviamente, usted sabe cómo esto invalida todo el propósito de un SecureString, pero lo repetiré de todos modos.
Si desea una línea, intente esto: (.NET 4 y superior solamente)
Donde securePassword es un SecureString.
fuente
[System.Net.NetworkCredential]::new('', $securePassword).Password
''
no es del mismo tipo que[String]::Empty
? TampocoNew-Object Net.Credential
funciona para mí: no se puede encontrar el tipo [Net.Credential]: verifique que el ensamblado que contiene este tipo esté cargadoDang justo después de publicar esto, encontré la respuesta profunda en este artículo . Pero si alguien sabe cómo acceder al búfer IntPtr no administrado y sin cifrar que expone este método, un byte a la vez para que no tenga que crear un objeto de cadena administrado para mantener mi seguridad alta, agregue una respuesta. :)
fuente
unsafe
palabra clave y achar*
, solo llamebstr.ToPointer()
y eche.SecureString.Length
.SecureString
no está tratando de ocultar el valor, está tratando de evitar que se realicen copias del valor en regiones que no pueden sobrescribirse de manera confiable, como memoria recolectada de basura, archivos de paginación, etc. La intención es que cuando laSecureString
vida finalice, absolutamente no queda copia del secreto en la memoria. No le impide hacer y filtrar una copia, pero nunca lo hace.En mi opinión, los métodos de extensión. son la forma más cómoda de resolver esto.
Tomé Steve en la excelente respuesta de CO y la puse en una clase de extensión de la siguiente manera, junto con un segundo método que agregué para admitir la otra dirección (cadena -> cadena segura) también, para que pueda crear una cadena segura y convertirla en una cadena normal después:
Con esto, ahora puede simplemente convertir sus cadenas de un lado a otro de la siguiente manera:
Pero tenga en cuenta que el método de decodificación solo debe usarse para realizar pruebas.
fuente
Creo que sería mejor encapsular
SecureString
funciones dependientes su lógica dependiente en una función anónima para un mejor control sobre la cadena descifrada en la memoria (una vez fijada).La implementación para descifrar SecureStrings en este fragmento:
finally
bloque.Obviamente, esto hace que sea mucho más fácil "estandarizar" y mantener a las personas que llaman en lugar de depender de alternativas menos deseables:
string DecryptSecureString(...)
función auxiliar.Observe aquí, tiene dos opciones:
static T DecryptSecureString<T>
que le permite acceder al resultado de laFunc
delegado desde la persona que llama (como se muestra en elDecryptSecureStringWithFunc
método de prueba).static void DecryptSecureString
es simplemente una versión "nula" que emplea unAction
delegado en casos en los que realmente no desea / necesita devolver nada (como se demuestra en elDecryptSecureStringWithAction
método de prueba).Ejemplo de uso para ambos se puede encontrar en el
StringsTest
clase incluida.Strings.cs
StringsTest.cs
Obviamente, esto no evita el abuso de esta función de la siguiente manera, así que tenga cuidado de no hacer esto:
¡Feliz codificación!
fuente
Marshal.Copy(new byte[insecureString.Length], 0, insecureStringPointer, (int)insecureString.Length);
lugar de lafixed
sección?[char]
, no[byte]
.String.Empty
, no la instancia recién asignada creada y devuelta porMarshal.PtrToStringUni()
.Creé los siguientes métodos de extensión basados en la respuesta de rdev5 . Fijar la cadena administrada es importante ya que evita que el recolector de basura la mueva y deje copias que no puede borrar.
Creo que la ventaja de mi solución es que no se necesita código inseguro.
fuente
System.String
objeto harán copias sin fijar ni borrar. Es por eso que esto no está integradoSecureString
.new char[length]
(o multiplicarlength
consizeof(char)
)action
delegado no cree copias de la cadena temporal, fijada y luego puesta a cero, este enfoque debe ser tan seguro o inseguro como élSecureString
mismo; para usar este último, una representación de texto sin formato también debe ser creado en algún momento, dado que las cadenas seguras no son construcciones de nivel OS; la seguridad relativa proviene de controlar la vida útil de esa cadena y garantizar que se borre después de su uso.SecureString
no tiene funciones miembro y operadores sobrecargados que hacen copias en todo el lugar.System.String
hace.NetworkCredential
constructor que acepta aSecureString
.Este código C # es lo que quieres.
%ProjectPath%/SecureStringsEasy.cs
fuente
Derivé de esta respuesta por sclarke81 . Me gusta su respuesta y estoy usando la derivada, pero sclarke81 tiene un error. No tengo reputación, así que no puedo comentar. El problema parece lo suficientemente pequeño como para no garantizar otra respuesta y podría editarlo. Así que lo hice. Fue rechazado. Entonces ahora tenemos otra respuesta.
sclarke81 Espero que veas esto (finalmente):
debiera ser:
Y la respuesta completa con la corrección de errores:
fuente
La solución de trabajo final de acuerdo con la solución sclarke81 y las soluciones de John Flaherty es:
fuente
fuente
BSTR
explícitamente, y no es un objeto .NET, por lo que el recolector de basura tampoco se ocupa de ello. Compare con stackoverflow.com/a/818709/103167 que se publicó 5 años antes y no tiene fugas.Si usa un en
StringBuilder
lugar de unstring
, puede sobrescribir el valor real en la memoria cuando haya terminado. De esa manera, la contraseña no se quedará en la memoria hasta que la recolección de basura la recoja.fuente