Revisión de la implementación: clave independiente, administrador y usuario

1

El administrador del sitio web necesita leer los datos del usuario. Por lo tanto, si la clave se deriva del pase de usuario, entonces el administrador debe conocer el pase de usuario, no es exactamente una buena idea.

Polynomial sugirió muy amablemente el siguiente esquema de encriptación.

Básicamente, lo que intentas hacer es crear una puerta trasera en la cuenta de cada usuario de manera que solo el usuario y un único usuario administrativo puedan acceder a sus datos. Esto se puede lograr de la siguiente manera:

us  = User salt  = Random unique value (not the same salt as used for authentication)
as  = Admin salt = Random unique value (not the same salt as used for authentication)

uk  = User key    = pbkdf2(user_pass, us, 256, rounds)
dk  = Data key    = random 256-bit key
ak  = Admin key   = pbkdf2(admin_pass, as, 256, rounds)
P   = RSA private key
p   = RSA public key

uk' = Encrypted user key    = dk ^ uk
dk' = Encrypted data key    = RSA_Encrypt(dk, p)
P'  = Encrypted private key = AES_Encrypt(P, ak)

m = message
iv = initialisation vector (random unique value)
c = ciphertext = AES_Encrypt(m, iv, dk)

Luego almacenamos uk ', dk' y iv con el registro de datos que estamos cifrando. Nos almacenamos con el registro de la cuenta de usuario. También almacenamos P 'y como con nuestro registro de cuenta de administrador. La clave pública P puede almacenarse en el código. El par de llaves es común entre los registros.

El descifrado del usuario funciona de la siguiente manera:

Compute uk from the user password and us.
Xor uk' with uk to retrieve dk.
Decrypt c using iv and dk, giving us m.

El descifrado de administrador funciona de la siguiente manera (la clave privada se almacena fuera de línea):

Compute ak from the admin password and as.
Decrypt P using AES_Decrypt(P', ak)
Decrypt dk using RSA_Decrypt(dk', P)
Decrypt c using iv and dk, giving us m.

He intentado implementar el esquema de Polynomial en PHP: este es el resultado . Ahora me gustaría saber si mi implementación es correcta y si es segura.

¡Muchas gracias por tu ayuda tan útil!

    
pregunta Surfer on the fall 16.01.2013 - 22:50
fuente

1 respuesta

1

Esto no es diferente al esquema que posé en esta pregunta , lo que tiene un poco de burla como demasiado complejo. El suyo es más sencillo (porque la autenticación del usuario se maneja por separado y solo se cubre aquí la seguridad / recuperación de los datos del usuario), pero aún está sucediendo un poco aquí con el cifrado de las claves de cifrado de varias maneras. Necesario, probablemente, pero aún complejo.

Recomendaría dos cambios. Primero, la clave RSA privada, en lugar de estar oculta detrás de las credenciales de una sola cuenta de administrador, podría almacenarse sin conexión. Supongo que la recuperación de datos de usuarios no es algo cotidiano, si se requiere un administrador para hacerlo (los administradores tienen mejores cosas que hacer todo el día que recuperar cuentas de usuario). Entonces, cuando sea necesario, un usuario con privilegios de administrador podría recuperar un HSM (o una unidad de disco con el archivo de claves si es barato) del almacenamiento con seguridad física, y utilizarlo con un programa sin conexión (que no sea parte del Aplicación PHP) para descifrar los datos del usuario.

La ventaja aquí es que no depende de una cuenta de administrador común, y por lo tanto no requiere una cuenta de administrador común, evitando la inevitabilidad de que las credenciales de la cuenta de administrador se escriban y luego caigan en manos "enemigas" . La clave y / o el programa de recuperación seguirían siendo accesibles solo para alguien con privilegios de administrador, quienes usarían sus propias credenciales de acceso personal para obtener la clave del almacenamiento e iniciar sesión en el programa. Esto también le da la posibilidad de una pista de auditoría; usted sabe exactamente qué credenciales se usaron para obtener la clave y ejecutar el programa, por lo que si alguna vez se sospecha que hay un compromiso, puede limitar la búsqueda.

Puede implementar cualquier pompa y circunstancia adicionales que considere necesarias para recuperar y utilizar la clave privada; solo asegúrate de que las medidas no sean tan draconianas que hagan que los usuarios quieran eludirlas (o, alternativamente, asegúrate de que las medidas eviten la evasión física, por lo general, esto requiere un $$$ $$$ grave). >

Segundo, también almacenaría p en la capa de datos, no en el código. Me doy cuenta de que este esquema está implementado en un sitio PHP, por lo que solo hay un lugar para publicar un cambio de código que actualice la clave pública. Sin embargo, debería la clave pública siempre debe cambiar, IMO es aún más fácil ingresar a la base de datos y actualizarla que publicar el cambio de código, y no es mucho más difícil obtener la clave pública (que es, una vez más, aparentemente no es extremadamente común; solo se necesitaría cuando el dk de un usuario cambiara, e incluso si eso cambia cada sesión, es una consulta de base de datos trivial.

Por supuesto, cambiar p en primer lugar hará que cualquier dk' encriptado con un p anterior sea obsoleto. Hay varias formas de mitigar esto:

  • Descifre y vuelva a cifrar la clave de datos de cada usuario siempre que cambie el par de claves RSA.
  • Almacene el "número de revisión" de la clave RSA que se utilizó por última vez para cifrar la clave de datos de un usuario, con el número de revisión actual almacenado junto con la clave pública actual, y mantenga varias revisiones anteriores de claves privadas en el almacenamiento.
    • Junto con obligar a los usuarios a cambiar su contraseña cada 90 días (regenerar y volver a cifrar sus claves de datos), la cantidad de claves antiguas que tendrá que mantener debe ser bastante baja.
  • Forzar a los usuarios a cambiar sus contraseñas cuando el par de llaves RSA cambia, restablece y vuelve a cifrar sus claves de datos con la nueva clave pública.
respondido por el KeithS 17.01.2013 - 00:18
fuente

Lea otras preguntas en las etiquetas