Encriptación de contraseña en Delphi
configuration encryption (15)
Necesito almacenar contraseñas de base de datos en un archivo de configuración. Por razones obvias, quiero cifrarlos (preferiblemente con AES). ¿Alguien sabe una implementación de Delphi que es fácil de introducir en un proyecto existente con> 10,000 líneas de código fuente históricamente crecido (URGH!)?
Aclaración: Fácil significa agregar la unidad al proyecto, agregando máx. 5 líneas de código donde se lee el archivo de configuración y listo. No debería tomar más de 15 minutos.
Otra aclaración: la contraseña es necesaria para crear una conexión a la base de datos, no para admitir un esquema de administración de usuarios para la aplicación. Entonces, usar hashes no ayuda. El motor de db comprueba si la contraseña es válida, no la aplicación.
Creo que Turbopower LockBox es una excelente biblioteca para criptografía:
http://sourceforge.net/projects/tplockbox/
No sé si es demasiado grande para tus usos, pero es muy fácil de usar y puedes encriptar una cadena con 5 líneas de código. Todo está en los ejemplos.
He usado esta biblioteca , realmente rápido de agregar. Pero wiki muestra algunas soluciones más.
Para fines de autenticación típicos, no necesita almacenar las contraseñas, solo necesita verificar si la contraseña introducida por el usuario es correcta. Si ese es su caso, puede almacenar una firma hash (por ejemplo, MD5) y compararla con la firma de la contraseña ingresada. Si las dos firmas coinciden, la contraseña ingresada es correcta.
Almacenar contraseñas encriptadas puede ser peligroso porque si alguien obtiene su contraseña "maestra" pueden recuperar las contraseñas de todos sus usuarios.
Si decide usar MD5, puede usar MessageDigest_5.pas que viene con Delphi (al menos está incluido en mi copia de Delphi 2007). También hay otras implementaciones con código fuente Delphi que puede elegir.
Por supuesto, Nick tiene razón, solo asumo que sabes lo que estás haciendo cuando dices que quieres gastar los 15 minutos en implementar una solución de seguridad. La biblioteca DCPCrypt también implementa una serie de algoritmos hashing si decide ir a esa (mejor) ruta.
TOndrej tiene el enfoque correcto. Nunca debe almacenar una contraseña con un cifrado reversible. Como se señaló correctamente, si su clave "maestra" alguna vez se vio comprometida, todo el sistema está en peligro. Usar un hash no reversible, como MD5, es mucho más seguro y puede almacenar el valor hash como texto sin cifrar. Simplemente hash la contraseña ingresada y luego compárala con el hash almacenado.
Apoyo la recomendación para la biblioteca DCPCrypt de David Barton. Lo he utilizado exitosamente en varios proyectos, y no tomará más de 15 minutos después de haber leído los ejemplos de uso. Utiliza la licencia de MIT, por lo que puede usarla libremente en proyectos comerciales y de otro modo. DCPCrypt implementa varios algoritmos, incluido Rijndael, que es AES.
También hay muchas implementaciones autónomas con googles (unidades únicas): la pregunta es en cuál confía, a menos que esté preparado para verificar la corrección de una biblioteca en particular.
Siempre uso el Turbopower Lockbox. Funciona bien y es muy fácil de usar. De hecho, lo uso exactamente para lo mismo, almacenando una contraseña en un archivo de texto de configuración.
Simplemente un recordatorio.
Si no necesita interoperar con otras bibliotecas de cifrado, entonces DCP o LockBox harían el trabajo.
PERO
si necesita que cumpla totalmente con las especificaciones de rinjdael, olvídese de los componentes gratuitos, la mayoría de las veces son "pésimos".
Como han señalado otros, para fines de autenticación, debe evitar almacenar las contraseñas con encriptación reversible, es decir, solo debe almacenar el hash de contraseña y verificar el hash de la contraseña proporcionada por el usuario contra el hash que ha almacenado. Sin embargo, ese enfoque tiene un inconveniente: es vulnerable a los ataques de tabla arcoiris , en caso de que un atacante obtenga la base de datos de la tienda de contraseñas.
Lo que debe hacer es almacenar los hashes de un valor de sal pre-elegido (y secreto) + la contraseña. Es decir, concatenar la sal y la contraseña, cortar el resultado y almacenar este hash. Al autenticarse, haga lo mismo: concatene su valor de sal y la contraseña proporcionada por el usuario, hash, luego verifique la igualdad. Esto hace que los ataques de tabla de arco iris sean inviables.
Por supuesto, si el usuario envía contraseñas a través de la red (por ejemplo, si está trabajando en una aplicación web o cliente-servidor), no debe enviar la contraseña en texto claro, de modo que en lugar de almacenar hash (salt + contraseña) debe almacenar y verificar contra hash (salt + hash (contraseña)), y hacer que su cliente haga un pre-hash de la contraseña proporcionada por el usuario y la envíe a través de la red. Esto también protege la contraseña de su usuario, en caso de que el usuario (como muchos) reutilice la misma contraseña para múltiples propósitos.
Recomiendo usar algún tipo de sal. No almacene cripta (contraseña) en el archivo de configuración, sino en la cripta de esta tienda (sal + contraseña). Como ''sal'' puede usar algo que se requiere para abrir la base de datos, ej. db_name + user_name. Para la función cripta puedes usar algún algoritmo conocido como AES, Idea, DES o algo tan simple como anotar cada byte con byte de alguna otra cadena, esa cadena será tu clave. Para que sea más diferente resolver, puede usar algunos bytes aleatorios y almacenarlos.
Entonces para almacenar:
- init_str: = 5 bytes aleatorios
- new_password: = salt + password // salt: = db_name + user_name
- crypted_password = xor_bytes (init_str + new_password, ''my keyphrase'')
- crypted_password: = init_str + crypted_password
- almacenar crypted_password en config, ya que esto serán bytes, puede hechizar o base64
Y para conectar:
- datos divididos leídos de la configuración en init_str y crypted_password
- new_password = xor_bytes (init_str + crypted_password, ''my keyphrase'')
- password: = remove (db_name + user_name) de new_password
Incluso si encriptas, me parece que tu clave de descifrado y la contraseña encriptada estarán en tu ejecutable, lo que significa que de ninguna manera es solo seguridad por oscuridad. Cualquiera puede tomar la clave de descifrado y las contraseñas encriptadas y generar las contraseñas sin procesar.
Lo que quieres es un hash unidireccional.
TurboPower LockBox 3 (http://lockbox.seanbdurkin.id.au/) utiliza la salazón automática. Recomiendo contra DCPCrypt de Barton porque los IV no están salados. En algunas situaciones, esta es una falla de seguridad muy grave.
A diferencia de un comentario anterior, la implementación de AES de LB3 es totalmente compatible con el estándar.
Un par de soluciones:
- No almacene la contraseña en absoluto. Si la base de datos admite autenticación integrada, úselo. El proceso puede configurarse para ejecutarse con una identidad específica y ser autenticado automáticamente por la base de datos
- Use las tiendas de certificados de Windows y un certificado para encriptar su contraseña. Si almacena la clave utilizada para cifrar su contraseña en su aplicación, de todos modos tiene muy poca seguridad, también debe proteger la clave.
Debe almacenarlo en un lugar donde solo el usuario actual también tenga acceso.
Básicamente hay dos formas de hacer esto:
- Guárdelo en un archivo cifrado EFS .
- Guárdelo en el almacenamiento local seguro .
Internet Explorer usa 2. Pero si puede obtener acceso local, puede descifrar tanto 1. como 2. si tiene la clave maestra y el algoritmo correctos (por ejemplo, iepv puede obtener las contraseñas de Internet Explorer).
Asi que:
Si puede, evite almacenar contraseñas.
Busque alternativas (como autenticación de Windows, servicios de directorio, etc.) primero.
--jeroen
Un sencillo pero para la mayoría de las aplicaciones, el sistema lo suficientemente fuerte está dado por la demostración de este Embarcadero: https://edn.embarcadero.com/article/28325