¿Cómo se podría implementar una base de datos de contraseñas compartidas?

2

En el formulario tradicional, una base de datos de contraseñas es similar a cualquier otro archivo de base de datos, excepto que el contenido se cifra mediante una clave derivada de una frase de contraseña ingresada por el usuario. El usuario ingresa su contraseña, descifra la base de datos, lee algunas entradas, escribe / cambia algunas otras entradas, vuelve a cifrar la base de datos y la vuelve a escribir en el disco.

Supongamos que queremos extender este concepto a un entorno compartido. Supongamos que nuestra base de datos tiene diez entradas ( 0 hasta 9 ) y tres usuarios ( Alice , Bob y Carl ), cada uno con su propia frase de contraseña exclusiva. Para complicar aún más la situación, Alice debería poder acceder a todas las entradas, Bob solo debería poder acceder a las entradas 0-4 y Carl solo debería poder acceder a las entradas 5-9. Si Alice cambia una de las entradas, Bob o Carl deberían ver el valor actualizado (si tienen acceso). Si Bob o Carl cambian una de las entradas a las que tienen acceso, Alice debería ver el valor actualizado.

Tengo curiosidad por saber si hay una manera en que algo como esto podría implementarse de manera segura. Todos los enfoques que he podido encontrar requieren que haya algún tipo de clave "maestra" almacenada junto a la base de datos, lo que deja una gran oportunidad para cualquiera que obtenga acceso al sistema de archivos o la memoria del servidor, o almacenar una copia encriptada única de cada conjunto de entradas para cada usuario. Pero eso rompería los escenarios en los que un usuario necesita actualizar un valor de manera que los demás usuarios puedan verlo.

¿Hay alguna forma de hacer esto, o de alguna manera sutil que se puedan modificar los requisitos para que el sistema sea menos paradójico?

    
pregunta smitelli 05.02.2015 - 04:05
fuente

3 respuestas

2

Pensé un poco en las respuestas que se han publicado hasta ahora, y hay una promesa interesante en la idea de usar un algoritmo de clave pública. Pensando en voz alta, cada usuario podría tener un par de claves pública / privada (donde cada clave pública se almacena en el servidor central junto con las bases de datos).

Almacenamiento de claves públicas en el servidor:

+-------+------------------------+
| Alice | [public key for Alice] |
+-------+------------------------+
| Bob   | [public key for Bob]   |
+-------+------------------------+
| Carl  | [public key for Carl]  |
+-------+------------------------+

Cada entrada se almacenaría encriptada, utilizando un cifrado simétrico con una clave por entrada que el servidor genera aleatoriamente cada vez que se escribe una entrada:

+---+-------------------------------------------------+
| 0 | symmetric_cipher([plaintext 0], [random key 0]) |
+---+-------------------------------------------------+
| 1 | symmetric_cipher([plaintext 1], [random key 1]) |
+---+-------------------------------------------------+
|   ...                                               |
+---+-------------------------------------------------+
| 9 | symmetric_cipher([plaintext 9], [random key 9]) |
+---+-------------------------------------------------+

Para el control de acceso, una tercera asignación podría almacenar la clave generada aleatoriamente para cada entrada, que se ha cifrado utilizando la clave pública de cada usuario autorizado:

+-------+---+-------------------------------------------------------+
| Alice | 0 | pubkey_cipher([random key 0], [public key for Alice]) |
+-------+---+-------------------------------------------------------+
| Bob   | 0 | pubkey_cipher([random key 0], [public key for Bob])   |
+-------+---+-------------------------------------------------------+
| Alice | 1 | pubkey_cipher([random key 1], [public key for Alice]) |
+-------+---+-------------------------------------------------------+
| Bob   | 1 | pubkey_cipher([random key 1], [public key for Bob])   |
+-------+---+-------------------------------------------------------+
|   ...                                                             |
+-------+---+-------------------------------------------------------+
| Alice | 8 | pubkey_cipher([random key 8], [public key for Alice]) |
+-------+---+-------------------------------------------------------+
| Carl  | 8 | pubkey_cipher([random key 8], [public key for Carl])  |
+-------+---+-------------------------------------------------------+
| Alice | 9 | pubkey_cipher([random key 9], [public key for Alice]) |
+-------+---+-------------------------------------------------------+
| Carl  | 9 | pubkey_cipher([random key 9], [public key for Carl])  |
+-------+---+-------------------------------------------------------+

(De lo que he leído, esto es algo de lo que hace GPG cuando envías un mensaje cifrado a múltiples destinatarios).

Cada usuario puede usar su clave privada para descifrar la clave de "entrada" simétrica que solo es válida para esa entrada específica. Esa clave les permitirá descifrar y leer esa entrada. Si necesitan cambiarlo y volver a guardarlo, pueden usar la misma clave que leen y sobrescribir, o el servidor podría generar una nueva clave de entrada y usar la clave pública para que cada usuario autorizado actualice la otra. filas.

La desautorización de un usuario sería tan simple como eliminar su fila de la tabla de asignación de usuario a entrada. Si existe la preocupación de que pueden haber almacenado una o más de las claves de entrada, todas pueden regenerarse de forma transparente para cada usuario restante sin ninguna intervención de su parte.

Parece que la principal preocupación sería cambiar para asegurar que los canales de comunicación cliente-servidor fueran seguros y que el cliente pueda mantener sus secretos en secreto.

    
respondido por el smitelli 05.02.2015 - 19:27
fuente
1

Para cada base de datos compartida, use una clave generada al azar para su cifrado. No almacene la clave tal como está, pero guárdela encriptada en tres copias (Alice tiene una clave cifrada con su contraseña, Bob tiene una clave cifrada con su contraseña, etc.). Si Alice quiere cambiar su contraseña de cifrado, primero descifre la copia de su clave y luego cifrada con la nueva contraseña; la clave de cifrado generada al azar subyacente no cambia en este escenario y las claves de Bob y Carl seguirán funcionando. - Supongo que sería preferible algún tipo de salado; si no, uno podría detectar fácilmente si dos usuarios han elegido la misma contraseña personal.

No sé exactamente cómo se configuraría el intercambio; Tendrá que transmitir la verdadera clave de cifrado de un usuario a otro sin fugas. ¿Tal vez podría dividir la clave en dos partes (XOR con una cadena aleatoria cryptosafe) y compartir una mitad dentro de su sistema de base de datos, y la otra mitad cortar y pegar desde la pantalla al correo electrónico?

Buena suerte.

    
respondido por el Magnus L 05.02.2015 - 18:00
fuente
0

Si ya está volviendo a cifrar la base de datos completa en cada escritura, entonces supongo que no sería tan grande como un salto mantener un almacén de datos separado para cada lector (o grupo de lectores de la misma manera). Podría ser más eficiente mantener un registro de transacciones para cada lector, y luego también especificar los permisos de escritura en los metadatos para cada lista de entrada / tabla a la que se hará referencia en la autenticación de transacciones de escritura.

Quizás una interfaz como esta:

<writer>: <key> = <value> -> <reader>(<permissions>)

Por ejemplo, este comando identificaría al escritor , establecería 3 en "hola" y definiría usuarios autorizados:

Alice: 3 = "hello" -> Alice(r+u+d), Bob(r)

Esto podría hacer que el cliente de Alice firme la cadena de transacción anterior y la cifre dos veces, una para Alice y otra para Bob, antes de enviar la transacción a la memoria persistente compartida por Alice, Bob y posiblemente Carl y un atacante. Cada uno de Alice y Bob verían y descifrarían la transacción, verificarían los permisos y autentificarían las firmas, la aplicarían a sus respectivas bases de datos y buscarían nuevas.

Para los permisos de grupo, reemplace Alice y Bob con nombres de grupo en el lado derecho del ejemplo y agregue metadatos según sea necesario (a través del mismo mecanismo o de otra manera). También es necesario que haya marcas de tiempo con cada transacción para proporcionar un orden claro de mutación, pero quería mantenerlo simple aquí.

Esencialmente describiendo encriptado / autenticado pub-sub , quizás con serializaciones a largo plazo del datos encriptados para cada persona y respaldados en la memoria persistente a largo plazo por cada persona para permitir un arranque rápido en nuevas máquinas y desalentar el almacenamiento a largo plazo en medios personales menos seguros (en lugar de hacer que atraviesen todo el libro de transacciones y procesarlos) todo secuencialmente durante el proceso de sincronización).

Ciertamente, existen sistemas como este con un enfoque lejos más eficiente / práctico ya implementado dentro de una base de código establecida. No conozco ninguna porque no he necesitado trabajar con un sistema como este hasta la fecha, pero buscaré y editaré la respuesta si la encuentro. Como idea final, observe cómo PGP admite múltiples destinatarios de un mensaje en una codificación; puede ofrecer alguna información.

    
respondido por el AJAr 05.02.2015 - 05:32
fuente

Lea otras preguntas en las etiquetas