2009-04-24 47 views
20

Necesito almacenar y encriptar una contraseña en un archivo (preferiblemente texto), que más tarde necesito poder descifrar. La contraseña es para otro servicio que utilizo y debe enviarse allí en texto sin cifrar (a través de SSL). Esto no es algo que pueda cambiar. ¿Cuáles son las mejores prácticas en esta área? ¿Cómo se puede lograr un cierto grado de protección de la contraseña de los usuarios malintencionados?¿Mejores prácticas para cifrar y descifrar contraseñas? (C# /. NET)

Mi plataforma es WinForms con C# /. NET 3.5.

Gracias.

+3

Debe cambiar el título "Mejores prácticas para el cifrado de contraseñas", ya que descifrar las contraseñas definitivamente NO es la mejor práctica. – devlord

+0

No, no debería; esa sería una pregunta completamente diferente. – Eyvind

+1

La mejor práctica para descifrar la contraseña es: NO HACERLO. – saluce

Respuesta

2

Como está utilizando WinForms y .Net, su código será visible en MSIL, incluso si está ofuscado y, por lo tanto, su código de descifrado está visible.

¿De quién está tratando de ocultar la contraseña? ¿El usuario de la aplicación no debe saber la contraseña?

Creo que va a necesitar hacer alguna validación de usuario, y me sentiría tentado de poner claves para el descifrado en una base de datos separada y proporcionar algún otro mecanismo para obtener eso que debería requerir autenticación. De esta forma, puede obtener el código de descifrado de la aplicación de winforms.

Sugiero también un servicio por separado que se ejecuta para cambiar regularmente las claves de descifrado de cifrado y actualiza todas las contraseñas en la base de datos.

13

Supongo que desea cifrar la contraseña, ya que estará en la máquina de los usuarios y que (posiblemente) podrán encontrarla y usarla. Si es así, básicamente estás jodido: no importa lo que hagas, dado que está en el dominio de los usuarios, podrán obtenerlo, descubrir el cifrado y obtener la contraseña para el cifrado (recuerda que usar Reflector - y sus clones - isn fuera del alcance de la mayoría) y descifrarlo y lo tienen. En resumen, todo lo que está haciendo es ofuscar la contraseña, no asegurarla.

Lo que recomendaría es moverlo fuera del control de los usuarios. Por ejemplo, ponga un servicio web que se comunique con el cliente y devuelva la contraseña de forma segura cuando se le solicite. Esto también le permite cambiar la contraseña, si es necesario en el futuro, y también le proporciona una forma de validar usuarios legítimos.

+0

+1, pero ¿cómo deberíamos garantizar el acceso al servicio web que devuelve la contraseña? –

+0

@Matthew cualquier sistema de autenticación estándar para los servicios funcionaría de maravilla. –

+0

@Robert: ¿te gustaría elaborar? Si el usuario solo puede llamar al servicio, el punto de seguridad es un poco discutible. ¿Qué no estoy recibiendo aquí? Gracias. – Eyvind

1

Encriptado en AES si debe guárdelo en un archivo de texto.

AES es mejor conocido como Rijndael en C#

http://www.obviex.com/samples/Encryption.aspx

mejor lugar sería el registro, ya que protegería a los demás usuarios de la máquina para llegar a ella.

Todavía no es el mejor almacenamiento en cualquier lugar que un usuario pueda llegar a ser peligroso. Un desarrollador de 1/2 vía decente puede cargar su aplicación en el reflector y encontrar su clave.

O hay System.Security.Cryptography.ProtectedData que alguien más sugirió.

Lo mejor que puede hacer en una máquina es crear un certificado y cifrar/descifrar con él cargado y bloqueado en el almacén de claves de la máquina. (Todavía tiene que tratar con la contraseña del certificado que está en su código)

+1

"Mejor lugar sería el registro, ya que protegería a otros usuarios de la máquina para llegar a él". Almacenar en el registro en comparación con un archivo de texto no afecta el acceso de otros usuarios de la máquina. – Joe

+0

@Joe, el HKEY_CURRENT_USER no es accesible para otros usuarios de la máquina. Ellos tienen su propia HKCU. Admin's excluidos por supuesto. http://en.wikipedia.org/wiki/Windows_registry Y luego está esto: http: //blogs.msdn.com/bclteam/archive/2006/01/06/509867.aspx –

+0

Pero tienes razón, yo No estoy enamorado de mi propia respuesta, pero con información limitada sobre con qué tiene que trabajar le doy opciones. Personalmente, me gusta usar un servicio web/aspx para proxy su contraseña para el usuario, pero luego tiene que obtener un certificado SSL, etc. –

0

No guarde la contraseña como parte del código. Además de los problemas de descompilación y confiar en la seguridad a través de la oscuridad, si cambias la contraseña necesitas volver a compilar y redistribuir tu aplicación.

Almacene la contraseña como un servicio web o en una base de datos a la que tenga acceso la aplicación. Te estás comunicando con un servicio en la web, por lo que estarás conectado, después de todo.

0

Una de las cosas más importantes son los permisos en el archivo. Incluso si el contenido está encriptado, debe asegurarse de que solo los procesos que necesitan acceso al archivo puedan leerlo.

6

System.Security.Cryptography.ProtectedData en el ensamblaje System.Security utiliza algunas API de Windows para cifrar datos con una contraseña que solo él conoce.

Una posible utilización de esto sería tener un servicio de Windows que realmente hace la operación que requiere la contraseña. La aplicación con la que interactúa el usuario llama al servicio mediante comunicación remota o WCF. Siempre que el servicio utilice DataProtectionScope.CurrentUser y el usuario del servicio sea diferente del usuario que inició sesión, la contraseña debe ser bastante segura.

Esto, por supuesto, supone que los usuarios se están ejecutando como usuarios limitados que no pueden modificar el servicio o ejecutar el programa como el usuario del servicio.

7

¿Por qué necesita descifrar la contraseña? Por lo general, se almacena y compara un hash salado de la contraseña. Si encriptas/descifras la contraseña, tienes la contraseña como texto sin formato nuevamente y esto es peligroso. El hash debe ser salado para evitar el hash duplicado si algunos usuarios tienen las mismas contraseñas. Para la sal puede tomar el nombre de usuario.

HashAlgorithm hash = new SHA256Managed(); 
string password = "12345"; 
string salt = "UserName"; 

// compute hash of the password prefixing password with the salt 
byte[] plainTextBytes = Encoding.UTF8.GetBytes(salt + password); 
byte[] hashBytes = hash.ComputeHash(plainTextBytes); 

string hashValue = Convert.ToBase64String(hashBytes); 

Puede calcular el hash salado de la contraseña y almacenarla dentro de su archivo. Durante la autenticación, calcula nuevamente el hash de las entradas de usuario y compara este hash con el hash de contraseña almacenado. Dado que debería ser muy difícil (nunca es imposible, siempre es cuestión de tiempo) obtener el texto sin formato de un hash, la contraseña está protegida contra la lectura como texto sin formato de nuevo.

Consejo: Nunca almacene ni envíe una contraseña sin cifrar. ¡Si obtiene una nueva contraseña, encripte lo antes posible!

+1

Como dije en la pregunta, debo descifrarlo porque el servicio acepta solo una contraseña en forma no encriptada. – Eyvind

+0

Si no puede evitarlo, usaría AES, pero tenga en cuenta que cualquier clave de cifrado puede leerse desde el ensamblado, por lo que no es realmente guardar. – Enyra

+0

Hola, ¿El cifrado SHA256 es lo suficientemente bueno para que el programa almacene contraseñas en un archivo de texto sin formato? Estoy buscando métodos de descripción para mi programa de almacenamiento de contraseñas, y no estoy seguro de cuál debería usar. – HelpNeeder

0

Dado que debe enviar la contraseña en forma no encriptada a través de la red, no hay nada que pueda hacer para protegerla al 100%.

AES es lo suficientemente bueno si necesita almacenar localmente, y hablando de disasms, rastreadores de red, etc. no es particularmente buena contra-argumento becuase lo mismo se puede hacer con cualquier programa (Seguro, ASM es más difícil que CIL pero es un punto menor).

Dicha protección con contraseña es lo suficientemente buena para evitar la recogida ocasional, no para evitar la descodificación por parte de profesionales.

+0

Como dijo, está encriptada a través de SSL –

+0

La contraseña es para otro servicio que utilizo, y debe enviarse allí en texto libre (a través de SSL) – majkinetor

1

Acabo de implementar algo como esto para almacenar una contraseña proporcionada por el usuario. Convertí el resultado encriptado en una cadena codificada en base 64, para poder almacenarlo fácilmente en la configuración de usuario de mi aplicación.

De su pregunta, parece que su usuario malintencionado está realmente utilizando su aplicación, por lo que esto solo proporcionará ofuscación. Aunque no se revelaría ninguna clave mediante el uso de Reflector, el texto sin formato sería visible en un depurador.

static byte[] entropy = { 65, 34, 87, 33 }; 

public string Password 
{ 
    get 
    { 
     if (this.EncryptedPassword == string.Empty) 
     { 
      return string.Empty; 
     } 

     var encrypted = Convert.FromBase64String(this.EncryptedPassword); 
     var data = ProtectedData.Unprotect(encrypted, entropy, DataProtectionScope.CurrentUser); 
     var password = Encoding.UTF8.GetString(data); 
     return password; 
    } 
    set 
    { 
     if (value == string.Empty) 
     { 
      this.EncryptedPassword = string.Empty; 
      return; 
     } 

     var data = Encoding.UTF8.GetBytes(value); 
     var encrypted = ProtectedData.Protect(data, entropy, DataProtectionScope.CurrentUser); 
     var stored = Convert.ToBase64String(encrypted); 
     this.EncryptedPassword = stored; 
    } 
} 
Cuestiones relacionadas