Generando par de llaves RSA (seguridad / rendimiento) en el servicio REST

0

Hay un servicio de API REST. Un punto final es responsable de la creación de cuentas de usuario. Se supone que cada usuario debe tener un par de claves RSA generado y almacenado en un servidor. Para evitar que las claves privadas sean leídas por un posible adversario, las claves privadas se codifican en PEM. El formato PEM se cifra con AES-256-CBC mediante una frase de contraseña. La frase de contraseña es la misma que la que usa un usuario para iniciar sesión.

Hasta ahora he estado generando un par de llaves dentro de un controlador de solicitudes. Pero eso en algunos casos lleva 10 segundos, lo que es indeseable.

¿Cuál sería una solución segura y de rendimiento para este problema? Quiero evitar almacenar una frase de contraseña en texto sin formato para su posterior cifrado.

    
pregunta antagon 20.06.2017 - 13:49
fuente

2 respuestas

2

Si lo entendí correctamente, está generando claves RSA en un servidor, manteniendo la clave pública en el servidor y enviando las claves privadas a los usuarios. Recomendaría en su lugar generar las claves en el lado del cliente y enviar la clave pública al servidor. Así es como se supone que se utiliza el cifrado asimétrico.

El tiempo necesario para generar claves RSA es inherente al algoritmo RSA, no hay mucho que puedas hacer al respecto.

Si debe generar las claves en el servidor, le sugiero que cambie de RSA a ECC . El proceso de generación de claves es mucho más rápido. Existen muchas bibliotecas para usar ECC. El algoritmo Curve25519 es una buena opción, pero hay alternativas .

Además, si solo necesita proteger las comunicaciones entre el cliente y el servidor, usar TLS 1.2 (o 1.3) con certificados de cliente es una solución mejor que rodar su propio criptográfico.

    
respondido por el A. Hersean 21.06.2017 - 14:38
fuente
1

Su descripción del servicio, incluso en comentarios, no está del todo clara, por lo que voy a describir algunas pautas generales de lo que necesita hacer para un sistema de este tipo, junto con el por qué y cómo.

  1. No genere claves asimétricas en el servidor. Es decir, siempre que sea posible, el trabajo del cliente. Esto no solo evita los recursos del servidor y la apertura a ataques de denegación de servicio, sino que también evita que el servidor tenga acceso a la clave privada del cliente.
  2. Cifre la clave privada en el cliente, antes de enviarla al servidor. Un sistema en el que el servidor puede ver la clave privada del cliente e incluso podría teóricamente almacenarla o descifrarla. no se puede confiar.
  3. Hashee la contraseña del usuario a través de una función de hash de contraseña segura (o función de derivación de clave) en el cliente, antes de enviarla al servidor. Al usar un esquema como este, los usuarios tienen claves privadas que están cifradas usando su contraseñas, no se puede permitir que el servidor sepa la contraseña del usuario incluso en la creación de cuenta o el inicio de sesión.
  4. Use diferentes sales en la función de derivación de clave para el cifrado del lado del cliente de la clave y el hashing del lado del cliente de la contraseña para la autenticación. Está bien usar el mismo algoritmo e incluso el mismo factor de trabajo para ambos. la clave de cifrado derivada de la contraseña y el hash de la contraseña del lado del cliente, pero deben tener diferentes sales para que, dado un hash (que el cliente hace cuando envía el hash de la contraseña al servidor), la clave de cifrado no puede ser determinada por ninguna operación .
  5. Vuelva a cargar el hash de la contraseña proporcionada por el cliente antes de almacenar / comparar en el servidor. Aunque en realidad se deriva de la contraseña ingresada por el usuario en lugar de ser la contraseña en sí, aún debe volver a aplicarla. hash antes de almacenarlo, de lo contrario, un actor malintencionado que recoja su tabla de contraseñas podría autenticarse como cualquier usuario (aunque no tendría suficiente información para descifrar las claves privadas). Esta última ronda de hash no tiene por qué ser particularmente lenta, ya que la entrada a la misma es la salida de fuerza bruta de una función de derivación de clave / derivación de clave.

Algunas otras notas:

  • Respaldo la sugerencia de A. Hersean de usar ECC en lugar de RSA, si puedes. RSA es un algoritmo asimétrico más antiguo y más ampliamente implementado, pero también es más lento generar y usar las claves y las claves en sí mismas son más largas, lo que requiere más almacenamiento.
  • Usted menciona (en un comentario) el uso de crypto para protegerse contra la inyección de SQL. Esta es una no-solución demasiado diseñada para un problema ya resuelto. Es como tratar de usar un rallador de queso para rebanar pan, cuando tienes un cuchillo de pan allí mismo: es un gran esfuerzo para algo que probablemente no funcionará bien. Utilice la herramienta adecuada para el trabajo; La solución para SQLi es utilizar consultas parametrizadas / procedimientos almacenados para el acceso a la base de datos y nunca concatenar cadenas proporcionadas por el usuario en las consultas (y, si eso falla, porque por alguna razón necesita para permitir que un usuario proporcione la cadena se puede usar para alguna parte de la consulta que no se puede parametrizar, use una función de saneamiento de entrada bien implementada y confiable en lugar de cifrar la cadena o intentar hacer cualquier otra forma para hacerlo seguro por su cuenta).
  • Hay muchos, muchos más riesgos para las aplicaciones web y los servicios web que SQLi. Ya que su sistema aparentemente involucra el paso de mensajes, algunos de los obvios a considerar son XSS y CSRF, aunque los servicios verdaderamente RESTful deben estar a salvo de ellos. Otros son ataques de entidad externa o recursivos XML (si utiliza XML), ataques de deserialización (si utiliza cualquier tipo de objetos serializados) y, por supuesto, las innumerables formas de ataques de denegación de servicio (de los cuales ya se ha expuesto). a uno, al permitir que los clientes le indiquen al servidor que realice una operación costosa).
  • Crypto es muy, muy difícil de hacer bien. Debería tener a alguien que realmente sepa lo que está haciendo, mirar su diseño completo (no solo el resumen parcial que nos ha proporcionado aquí), y luego echar un vistazo a su código, ya que el cifrado puede ser increíblemente frágil y, si lo obtiene, una pequeña cosa mal, puede volverse sin valor.
respondido por el CBHacking 28.09.2018 - 10:18
fuente

Lea otras preguntas en las etiquetas