2010-03-10 11 views
40

¿Se puede simplificar esto a un trazador de líneas? Siéntase libre de reescribirlo por completo siempre que secureString se inicialice correctamente.Uso de SecureString

SecureString secureString = new SecureString(); 
foreach (char c in "fizzbuzz".ToCharArray()) 
{ 
    secureString.AppendChar (c); 
} 
+1

Véase también: http://stackoverflow.com/questions/1800695/c-securestring-question –

+1

No se olvide de hacer su 'SecureString' de solo lectura. – Greg

Respuesta

38

Usted podría utilizar LINQ:

"fizzbuzz".ToCharArray().ToList().ForEach (p => secureString.AppendChar (p)); 
+1

+1 En realidad, creo que es lo mismo que @Tod propuesto, pero con menos líneas. – Javier

+0

Supongo que puedo incluir esto en un método de extensión para obtener lo que busco: processInfo.Password = new SecureSring() .FromString ("fizzbuzz") –

+25

Puede evitar la operación adicional .ToList() con lo siguiente: 'Array.ForEach (" fizzbuzz ".ToCharArray(), secureString.AppendChar);' –

25

Aparte de utilizar código no seguro y una char*, no hay una (mucho) mejor manera.

El punto aquí no es para copiar el contenido de SecureString a/desde cadenas normales. La constante "fizzbuzz" es la fuga de seguridad aquí.

+0

Dale un golpe - +1. Además, los cambios adicionales que necesita realizar para permitir el código inseguro niegan cualquier "ahorro" en las líneas de código. –

+1

¿La mayoría de las contraseñas no se originan en la mayoría del software como cadenas y luego deben convertirse a SecureString? No estoy seguro de lo que quiere decir con "no copiar el contenido de SecureString de la cadena normal". En circunstancias normales, eso sería una contraseña de cadena. "fizzbuzz" es solo un homenaje. –

+0

Sí, y eso reduce en gran medida la usabilidad de SecureString. –

13
var s = "fizzbuzz".Aggregate(new SecureString(), (ss, c) => { ss.AppendChar(c); return ss; }); 
+0

Esto es muy elegante. –

16

Ligera mejora en la respuesta de Sascha sustitución de la lambda con un grupo método

"fizzbuzz".ToCharArray().ToList().ForEach(ss.AppendChar); 
38

Sólo tiene que utilizar NetworkCredential. Tiene la lógica de conversión incorporada.

SecureString ss = new NetworkCredential("", "fizzbuzz").SecurePassword; 

Como otros han señalado, todas estas técnicas tira de los beneficios de seguridad de SecureString, pero en ciertas situaciones (tales como pruebas de unidad) esto puede ser aceptable.

Actualización:

Como se señaló en los comentarios, NetworkCredential también se puede utilizar para convertir un SecureString de nuevo a una cadena.

string s = new NetworkCredential("", ss).Password; 
+2

y no está disponible antes .Net 4.0 –

+2

¡Elegante! E incluso funciona en ambas direcciones. –

+0

@JohannesOvermann, ¿qué quiere decir con * ambas direcciones *? (Por lo que puedo ver, 'NetworkCredential' consume una contraseña de texto sin formato o una contraseña' SecureString', pero solo expone una contraseña de texto sin formato en el primer caso). – CodeFox

8

Aquí es una forma NetworkCredential clase de .NET hacerlo:

SecureString secureString; 
fixed (char* chPtr = plainString) 
    secureString = new SecureString(chPtr, plainString.Length); 

feo pero probablemente el más eficiente.

+7

Tenga en cuenta que el uso de 'fixed' requiere un bloque' inseguro', que a su vez requiere que el compilador cambie '/ unsafe'. – DonBoitnott

3

Desde SecureString utiliza la interfaz IDispose. En realidad podrías hacerlo así.

SecureString secure = new SecureString(); 
foreach(var character in data.ToCharArray()) 
    secure.AppendChar(character); 

En esencia, el data habría un parámetro.

Si utiliza el using para ayudar a aliviar los recursos; querrás tener cuidado con el alcance. Pero esta puede ser una alternativa beneficiosa, dependiendo del uso.

Actualización:

En realidad se podría hacer un método de firma completa:

public static SecureString ConvertStringToSecureString(this string data) 
{ 
    var secure = new SecureString() 
    foreach(var character in data.ToCharArray()) 
     secure.AppendChar(character); 

    secure.MakeReadOnly(); 
    return secure; 

} 

para la desencriptación que se quiere hacer:

public static string ConvertSecureStringToString(this SecureString data) 
{ 
    var pointer = IntPtr.Zero; 
    try 
    { 
      pointer = Marshal.SecureStringToGlobalAllocUnicode(data); 
      return Marshal.PtrToStringUni(pointer); 
    } 
    finally 
    { 
      Marshal.ZeroFreeGlobalAllocUnicode(pointer); 
    } 
} 

La siguiente article le dará algo de información adicional también.

0

menor cantidad de código porque .ToList() no se requiere para esto:

Array.ForEach("fizzbuzz".ToCharArray(), secureString.AppendChar);