¿Verificación de mensaje de la API sin almacenar la clave privada?

10

Estoy en el proceso de implementar una API pública para mi servicio web. La seguridad es una preocupación clave ya que el dinero está involucrado.

Parece que la práctica común actual para "autenticar" usuarios en solicitudes API es confirmando la autenticidad del mensaje, haciendo que el usuario envíe un HMAC de los parámetros (incluido un único punto), para cada solicitud.

Esto está bien, pero utiliza un secreto compartido: tanto el servidor como el cliente tienen que almacenar la clave privada para generar el HMAC.

No me gusta esto. ¿De qué sirve ir a todas las trampas con contraseñas de salado / hash, si luego voy a comenzar a almacenar secretos compartidos sin cifrar en la base de datos?

¿Hay una mejor manera? Estaba pensando en usar GPG, y hacer que el usuario proporcione su propia clave pública GPG para que yo la almacene; Entonces podrían firmar mensajes usando su clave privada. Sin embargo, me temo que esto podría ser un poco molesto para los usuarios de Windows para jugar.

En general, ¿no es la firma de clave pública / privada una forma mucho mejor de hacer esto? Debe haber alguna razón por la que todos elijan HMAC con un secreto compartido ... ¿qué me falta?

Por supuesto, estableceré límites en las interacciones con los clientes a través de las API, proporcionaré notificaciones y limitaremos la eliminación de dinero del sistema, pero aún se podría hacer mucho daño si se filtraran los secretos compartidos.

    
pregunta Jhong 06.06.2013 - 04:45
fuente

3 respuestas

1

user26802 es correcto, la respuesta es velocidad. Imagine una API como Amazon SQS en la que los clientes están dejando y recogiendo muchos mensajes pequeños a altas velocidades, con un cifrado lento en el cliente y un descifrado lento en el servidor ralentizaría considerablemente ese servicio.

Se podría imaginar un enfoque mixto en el que los clientes realizaran una llamada autenticada con la firma de clave privada para establecer una clave simétrica a corto plazo. Si sus claves estuvieran comprometidas, solo tendría una pequeña ventana de vulnerabilidad antes de que expiraran las claves. Ahora, si el atacante tiene acceso permanente a su sistema, no está mejor.

Otra cosa que se debe tener en cuenta, si un atacante ha comprometido su almacenamiento de claves y puede robar todas las claves de firma, también puede reemplazar una clave pública y aún poder crear solicitudes como otro usuario.

    
respondido por el u2702 18.06.2013 - 18:41
fuente
3

Hice la misma pregunta ayer mismo, pero mientras tanto, he encontrado lo que creo que responderá a nuestras dos preguntas: SRP. Esta pregunta tiene la mejor respuesta que he encontrado hasta ahora. Aquí hay una referencia a SRP . El principal problema con SRP es que no hay implementaciones modernas que puedan usarse en el nivel de la aplicación.

Editar para agregar más información de mi investigación:

Decidí usar un almacén de sesión respaldado por base de datos, por lo que aún cumple con la definición de sin estado. Esto requiere que SSL sea el único protocolo para la comunicación, lo que elimina MITM y los ataques de reproducción.

  • Use bcrypt para almacenar contraseñas en DB
  • use la autenticación de dos factores, como Authy o Google Authenticator, esto no cumple con el requisito de que no haya dependencias externas, pero en mi caso, estoy de acuerdo con eso. Evita que un usuario filtre su contraseña; los atacantes todavía necesitan el dispositivo TFA del usuario.
  • Tiene un campo de ID de sesión y duración de sesión (en segundos) en cada registro de usuario
  • Tras la autenticación exitosa (autenticación típica, el usuario envía un ID de usuario y una contraseña, usa bcrypt para hash password usando pw hash almacenado), compara hashes, etc.)
  • Una vez que la contraseña haya sido exitosa, genere guid criptográficamente y almacene en db, junto con el tiempo que desea mantener la sesión activa
  • enviar este ID de sesión como respuesta a auth
  • Si desea una verdadera falta de estado de apatía, solicite al cliente que HMAC marque todas las solicitudes con este ID: él puede guardar el ID, no tiene que enviarlo a usted
  • verifique la solicitud mediante la solicitud de hashing con el sid almacenado, compare con el hash que le envió
  • en cada solicitud, verifique que no haya pasado el tiempo de caducidad; no necesita un proceso que caduque las comprobaciones, solo verifíquelas cada vez que el cliente intente una llamada a la API.

He comprometido y he utilizado el almacenamiento de sesión seguro de express-js, el cual SÍ usa una cookie del lado del cliente, pero la cookie está firmada con un secreto compartido que todos mis servidores de aplicaciones conocen, por lo que cumple con la definición sin estado en que la cookie no es exclusivo del servidor al que está conectado el cliente, ya que la cookie aún está en el dominio de mi servidor de aplicaciones

    
respondido por el regretoverflow 06.06.2013 - 18:06
fuente
1

La criptografía de clave pública es más lenta y requiere más recursos para obtener la misma fuerza criptográfica que un secreto compartido más pequeño.

Consulte: enlace

Esto probablemente no será un problema si está creando un sistema de bajo volumen, pero una vez que llegue a sistemas a gran escala, es posible que deba justificar el costo adicional para su organización y sus clientes / clientes.

Si le preocupa almacenar secretos simétricos, probablemente debería cifrarlos de todos modos.

    
respondido por el user26802 06.06.2013 - 18:53
fuente

Lea otras preguntas en las etiquetas