Sistema para autenticar de forma segura la adquisición de contenido

3

Tengo problemas para diseñar un sistema para contenido autenticado de mi sitio distribuido por otras personas. Estoy trabajando en Ruby on Rails, pero no creo que a nivel teórico mi pregunta no esté restringida a ese marco. Para no revelar demasiado, mi sitio (llamémoslo www.site.com) ayuda a las empresas a mantener un inventario de quién ha comprado qué artículo, y permite a los clientes ver su historial de compras.

Por lo tanto, tengo el siguiente problema:

  1. Supongamos que Alice vende hamburguesas con queso. Alice hace una cuenta en site.com y registra sus hamburguesas con queso como un artículo que vende. En consecuencia, site.com almacena la hamburguesa con queso de Alice en una base de datos SQL con el id 92314
  2. Bob es un cliente en el puesto de hamburguesas con queso de Alice y recientemente ha comprado una hamburguesa con queso.
  3. A Alice le gustaría contarle a Bob sobre site.com y su capacidad para rastrear las compras. Por lo tanto, Alice envía una solicitud a site.com para devolver hashA que corresponde al elemento con id 92314.
  4. Bob visita www.site.com/purchase/hashA y se le solicita que cree una cuenta o inicie sesión para registrar su nueva compra de hamburguesa con queso de Alice's Delicious y Delectable cheeseburgers.
  5. Charlie también visita el puesto de hamburguesas de Alice y compra una hamburguesa con queso.
  6. A Alice también le gustaría contarle a Charlie sobre site.com y envía una solicitud que genera hashB para que Charlie la use de la misma manera.

Mi pregunta es, ¿cómo puedo crear un esquema que pueda generar hashA y hashB de manera que mi servidor web pueda buscar los elementos de manera eficiente? Sospecho que hashB puede generarse a partir de hashA usando algún tipo de cifrado usando hashA como semilla. No sé cómo, al recibir hashA o hashB , site.com sabrá que corresponde al ítem 92314. Sospecho que usando un nonce ayudará.

Las cosas que me gustaría evitar incluyen:

  • Hacer que Charlie use hashA después de que lo haya usado Bob
  • Exponer el id 92314 al usuario
  • Tener un único punto de error (es decir, una clave única que cifra los hashes para todos los identificadores)
  • Se rompen las cosas si Charlie usa hashB antes de que Bob use hashA .

Descargo de responsabilidad: mi experiencia es más en gráficos de computadora y menos en desarrollo web o criptografía, por lo que apuntar a Google es útil. Si esto pertenece a cualquiera de los otros sitios de stackexchange (Criptografía, Programadores, etc.). No dude en hacérmelo saber y lo moveré.

    
pregunta Mokosha 29.09.2013 - 19:58
fuente

2 respuestas

4

Si entiendo tu problema correctamente:

  • Alice se autentica con el servidor. Cuando Alicia habla con el Servidor, el Servidor sabe que es Alicia.
  • Alice tiene un "elemento" en el servidor que corresponde a algún ID en la base de datos.
  • Alicia puede otorgar algún tipo de acceso al elemento a las personas que elija, por ejemplo. Bob y Charlie.
  • Bob y Charlie se conectarán al servidor luego , usando un token que Alicia les envió y que representa el derecho de acceso al servidor.
  • La ID no debe revelarse a nadie que se encuentre fuera del servidor. Los tokens para Bob y Charlie deben ser distintos entre sí, y no ser adivinables.

Esto apunta a esta solución genérica:

  • Cuando Alice obtiene un nuevo token T del servidor, el servidor recuerda que "el valor del token T es para el elemento 92314". Esta memoria es, por ejemplo, una nueva fila en una tabla de base de datos dedicada.
  • Cada vez que Alice solicita un nuevo token T , el Servidor genera uno al azar. Si los valores del token son lo suficientemente grandes (16 bytes o más), la probabilidad de que el Servidor genere dos veces el mismo valor del token es despreciable. Alternativamente, dado que el Servidor recuerda todos los tokens producidos, puede imponer la unicidad.
  • Opcionalmente , el token T puede tener un límite de tiempo (el Servidor olvida los tokens emitidos después de un tiempo) y / o un disparo (el Servidor olvida los tokens emitidos después de su uso).
  • Opcionalmente , cuando Alice obtiene una ficha T , puede decirle al servidor "esto es para Bob" para que cuando Bob se conecte, ya se hayan completado partes del formulario de registro.

Con un límite de tiempo, la cantidad de tokens para recordar, con su asociación con la ID del elemento y la información opcional del usuario, puede permanecer acotada y, por lo tanto, ser manejable tecnológicamente.

Una optimización es descargar esta memoria en Bob. Esto significa que el servidor codificará en el valor del token en sí mismo lo que le hubiera gustado recordar. En ese sentido, la memoria es libre. Sin embargo, esto requiere criptografía, porque:

  • No debería ser factible que personas externas generen valores de token que el Servidor acepte; La generación de tokens debería ser un monopolio de servidor. Esto apunta a la necesidad de un MAC .

  • El contenido del token, que el Servidor desea recordar, es confidencial. Por lo tanto, también se necesita el cifrado.

En ambos casos, hay claves, y eso es inevitable: claves son conocimiento, y en criptografía, conocimiento es poder. Todos pueden comprar los mismos equipos, por lo que si el Servidor puede generar valores de token y otras personas no pueden, entonces el Servidor debe saber algo que las otras personas no saben. Ese "algo" es lo que los criptógrafos llaman una clave. La criptografía puede ayudarlo a concentrar ese "conocimiento" en un valor muy pequeño, no mutante, digamos una secuencia de 128 bits (16 bytes). Pero no puede hacer que desaparezca por completo.

El esquema para este servidor "sin memoria" es:

  • Dados los datos D , el valor del token T es el cifrado + MAC de D . Para que los tokens de Bob y Charlie sean distintos, D puede contener un contador global, la fecha de producción y / o algunos bytes aleatorios. D también contendrá la ID del elemento y todo lo que el Servidor quiera "recordar" sobre este token.

  • Al recibir un token T , el Servidor comprueba el MAC y lo desencripta, obteniendo D , por lo tanto, todo lo que se necesita para registrar a Bob (o Charlie) .

  • Opcionalmente , cuando se crea la cuenta de Bob, el valor de token T utilizado por Bob se registra en la cuenta de Bob. Por lo tanto, cuando se recibe un token T ', el Servidor puede verificar si T' aún no se ha utilizado para crear una cuenta. Esto es para evitar que el propio Bob le dé copias de su token a sus amigos. Esto implementa una propiedad "única" para el token.

La combinación correcta de cifrado y MAC es una cuestión de sutileza . Si hace este camino, se recomienda utilizar un modo de cifrado que realice tanto el cifrado como el MAC de forma criptográfica correcta; es decir GCM o EAX .

    
respondido por el Thomas Pornin 29.09.2013 - 20:49
fuente
5

Whoa! Estás complicando demasiado el tema en un alto grado; El asunto en cuestión es mucho más simple.

Tabla 1 ( products )

product_id - product_name - product_key

product_key simplemente puede ser el sha1() de product_id , product_name y algunos bytes aleatorios. O, mejor, solo toma 16 bytes al azar y pásalos a sha1() .

Tabla 2 ( requests / invitations )

request_id - product_id - request_key - valid

request_key se genera de la misma manera: el producto sha1() de request_id , product_id , y algunos bytes aleatorios. O, simplemente, el sha1() de unos 16 bytes aleatorios.

Ahora, cuando Alice quiere decirle a Bob sobre site.com , se generará una fila en la "Tabla 2" y ella simplemente le enviará el enlace site.com/purchase/request_key .

Lo mismo sucede cuando le dices a Charlie; se generará una nueva fila en la "Tabla 2" (nuevo request_key ), por lo tanto, un nuevo enlace. Una vez que se visita el enlace, verifica si valid es true . Cuando se usa la clave, establece valid en false .

  • La clave solo se puede usar una vez.
  • La ID no está expuesta.
  • Sin cifrado sofisticado.
  • Cada clave de solicitud es independiente.
respondido por el Adi 29.09.2013 - 20:41
fuente

Lea otras preguntas en las etiquetas