crypto - how to encrypt a password in javascript
Encriptación de contraseña bidireccional sin SSL (13)
- Genera una clave aleatoria en el servidor (estoy usando php).
- Guarde la clave en una sesión y también envíe la clave en una variable de JavaScript.
- En el formulario enviado, utilice Triple DES en javascript con la clave para encriptar la contraseña.
Esto evita enviar la contraseña en el borrado por el cable, pero requiere que envíe la clave en el espacio libre sobre el cable, lo que permitiría que cualquier persona que esté escuchando descodifique la contraseña.
Se ha dicho antes y lo diré de nuevo: ¡no trates de inventar tus propios protocolos criptográficos! Existen protocolos establecidos para este tipo de cosas que han sido creados, revisados por pares, golpeados, pirateados, empujados y pinchados por profesionales, ¡úsalos! Ninguna persona podrá llegar a algo mejor que la comunidad de seguridad y criptografía trabajando juntas.
Estoy utilizando la API de Twitter básica-auth ( ya no está disponible ) para integrar Twitter con el sistema de comentarios de mi blog. El problema con esta y muchas otras API web es que requieren el nombre de usuario y la contraseña del usuario para hacer algo útil. No quiero lidiar con la molestia y el costo de instalar un certificado SSL, pero tampoco quiero que se pasen las contraseñas por cable en texto claro.
Supongo que mi pregunta general es: ¿cómo puedo enviar datos confidenciales a través de un canal inseguro?
Esta es mi solución actual y me gustaría saber si hay agujeros en ella:
- Genera una clave aleatoria en el servidor (estoy usando php).
- Guarde la clave en una sesión y también envíe la clave en una variable de JavaScript.
- En el formulario enviado, utilice Triple DES en javascript con la clave para encriptar la contraseña.
- En el servidor, descifre la contraseña usando la clave de la sesión y luego destruya la sesión.
El resultado final es que solo la contraseña cifrada se envía por cable y la clave solo se usa una vez y nunca se envía con la contraseña. ¿Problema resuelto?
Cuando la clave se envía entre el cliente y el servidor, es texto claro y sujeto a intercepción. Combine eso con el texto encriptado de la contraseña y descifre la contraseña.
Diffie-Hellman es una buena solución. Si solo necesita autenticarlos y no transmitir realmente la contraseña (porque la contraseña ya está almacenada en el servidor), puede usar Autenticación HTTP Digest o alguna variación de la misma.
Entonces, ¿cómo es esto más seguro? Aunque haya asegurado el navegador <> su servidor, ¿qué pasa con el resto de Internet (su servidor <> twitter)?
En mi humilde opinión, es inaceptable pedir un nombre de usuario y contraseña de otro servicio y esperar que las personas ingresen eso. Y si te importa tanto, no los integre hasta que no se hayan equivocado y vuelva a habilitar OAuth . (Lo soportaron por un tiempo, pero lo deshabilitaron hace unos meses).
Mientras tanto, ¿por qué no ofrecer OpenID? Cada cuenta de Google, Yahoo !, VOX etc. tiene una. La gente puede no estar al tanto, pero las posibilidades son realmente altas de que ya tengan OpenID. Revisa esta lista para ver a qué me refiero.
No necesita tener un certificado en su servidor; depende del cliente si están dispuestos a hablar con un servidor no autenticado. El acuerdo clave aún se puede realizar para establecer un canal privado. Sin embargo, no sería seguro enviar credenciales privadas a un servidor no autenticado, razón por la cual no se ve SSL utilizado de esta manera en la práctica.
Para responder a su pregunta general: simplemente envíela. Creo que su verdadera pregunta general es: "¿Cómo envío datos sensibles a través de un canal inseguro y lo mantengo seguro?" No puede.
Parece que ha decidido que la seguridad no vale los $ 10-20 por mes que costaría un certificado, y para proteger las contraseñas de Twitter, eso es probablemente cierto. Entonces, ¿por qué pasar el tiempo para proporcionar la ilusión de seguridad? Simplemente deje en claro a sus usuarios que su contraseña se enviará sin restricciones y les permitirá tomar su propia decisión.
Su método tiene un defecto: si alguien interceptara la transmisión de la clave al usuario y la respuesta encriptada del usuario, podría descifrar la respuesta y obtener el nombre de usuario / contraseña del usuario.
Sin embargo, hay una forma de enviar información de forma segura a través de un medio no seguro siempre que la información no sea modificada en tránsito conocida como el algoritmo Diffie-Hellman . Básicamente, dos partes pueden calcular la clave compartida utilizada para encriptar los datos en función de sus conversaciones; sin embargo, un observador no tiene suficiente información para deducir la clave.
Sin embargo, establecer la conversación entre el cliente y el servidor puede ser complicado y consumir mucho más tiempo que simplemente aplicar SSL a su sitio. Ni siquiera tiene que pagar, puede generar un certificado autofirmado que proporcione el cifrado necesario. Esto no protegerá contra los ataques de hombre en el medio, pero tampoco lo hará el algoritmo de Diffie-Hellman.
Implementé un enfoque diferente
- Servidor: nombre de usuario y contraseña-hash almacenados en la base de datos
- Servidor: envíe un desafío con el formulario para solicitar la contraseña, guárdela en la sesión con una marca de tiempo y la dirección IP del cliente
- Cliente: hash la contraseña, concat challenge | username | passwordhash, hash it nuevamente y lo publica en el servidor
- Servidor: verifique la marca de tiempo, IP, haga la misma concatenación / hash y compárela
Esto se aplica a una transmisión de contraseña. Usarlo para datos significa usar el hash final como la clave de cifrado para el texto plano y generar un vector de inicialización aleatorio transmitido con el texto de cifrado al servidor.
¿Algún comentario sobre esto?
¿Cómo puedo enviar datos confidenciales a través de un canal inseguro?
Con una clave secreta precompartida. Esto es lo que intenta en su solución sugerida, pero no puede enviar esa clave sobre el canal inseguro. Alguien mencionó DH, lo que te ayudará a negociar una clave. Pero la otra parte de lo que SSL hace es proporcionar autenticación, para evitar ataques de intermediarios para que el cliente sepa que está negociando una clave con la persona con la que intenta comunicarse.
El consejo de Chris Upchurch es realmente la única buena respuesta que hay para el 99.99% de los ingenieros: no lo hagas. Deje que otra persona lo haga y use su solución (como los tipos que escribieron el cliente / servidor SSL).
Creo que la solución ideal aquí sería conseguir que Twitter apoye OpenID y luego usar eso.
Un certificado SSL que se autofirma no cuesta dinero. Para un servicio gratuito de Twitter, probablemente sea bueno para los usuarios.
A OLI
En su aproximación, por ejemplo, estoy en la misma subred con el mismo enrutador, así que obtengo la misma ip que mis colegas en mi trabajo. Abrí la misma URL en el navegador, por lo que el servidor genera la marca de tiempo con la misma IP, luego uso tcp / ip dump para olfatear la contraseña hash o no hash de la conexión de mis colegas. Puedo oler todo lo que envía. Así que tengo todos los hashes de su formulario, también tiene la marca de tiempo (mi) y la misma ip. Entonces envío todo usando la herramienta de publicación y oye, estoy loggen in.
Si no desea usar SSL, ¿por qué no prueba otro protocolo, como kerberos?
Una descripción básica está aquí: http://www.kerberos.org/software/tutorial.html
O si desea profundizar un poco más, consulte http://www.hitmill.com/computers/kerberos.html
Tengo un problema similar (querer cifrar datos en formularios sin pagar un certificado SSL), así que busqué algo y encontré este proyecto: http://www.jcryption.org/
No lo he usado todavía, pero parece fácil de implementar y pensé que lo compartiría aquí en caso de que alguien más esté buscando algo así y se encuentre en esta página como yo lo hice.
API y OAuth
En primer lugar, como han dicho otros, no deberías estar usando la contraseña de un usuario para acceder a la API, debes obtener un token de OAuth . Esto le permitirá actuar en nombre de ese usuario sin necesidad de su contraseña. Este es un enfoque común utilizado por muchas API.
Intercambio de llaves
Si necesita resolver el problema más general de intercambiar información a través de conexiones inseguras, existen varios protocolos clave de intercambio mencionados en otras respuestas.
En general, los algoritmos de intercambio de claves son seguros para los intrusos, pero debido a que no autentican la identidad de los usuarios, son vulnerables a los ataques man-in-the-middle.
De la página de Wikipedia sobre Diffie Hellman :
En la descripción original, el intercambio de Diffie-Hellman por sí mismo no proporciona la autenticación de las partes que se comunican y, por lo tanto, es vulnerable a un ataque de hombre en el medio. Una persona en el medio puede establecer dos intercambios de clave distintos de Diffie-Hellman, uno con Alicia y el otro con Bob, enmascarando efectivamente a Alicia con Bob, y viceversa, permitiendo al atacante descifrar (y leer o almacenar) luego volver a encriptar los mensajes pasaron entre ellos. Por lo general, se necesita un método para autenticar a las partes que se comunican entre sí para evitar este tipo de ataque. Las variantes de Diffie-Hellman, como STS , se pueden usar para evitar este tipo de ataques.
Incluso STS es inseguro en algunos casos donde un atacante puede insertar su propia identidad (clave de firma) en lugar del remitente o el receptor.
Identidad y Autenticación
Este es exactamente el problema que SSL está diseñado para resolver, al establecer una jerarquía de autoridades de firmas ''confiables'' que en teoría verificaron quién posee un nombre de dominio, etc., alguien que se conecta a un sitio web puede verificar que efectivamente se están comunicando con el servidor de ese dominio. , y no con un hombre en el medio que se ha colocado en el medio.
Puede crear un certificado autofirmado que proporcione la configuración necesaria para encriptar la conexión, pero no lo protegerá de los ataques intermedios por la misma razón que no lo hará el intercambio de claves no autenticado de Diffie-Hellman.
Puede obtener certificados SSL gratuitos válidos durante 1 año en https://www.startssl.com/ - Los uso para mis sitios personales. No son tan ''confiables'' sea lo que sea lo que signifique, ya que solo realizan controles automáticos a las personas que solicitan uno, pero es gratis. También hay servicios que cuestan muy poco (£ 10 / año desde 123-Reg en el Reino Unido).
El problema con la seguridad de javascript en el lado del cliente es que el atacante puede modificar el javascript en tránsito a una simple {return input;}, lo que hace que su elaborado argumento de seguridad resulte innecesario. Solución: utilice el RSA proporcionado por el navegador (es decir, no transmitido). Por lo que sé, aún no está disponible.