Si un atacante tiene acceso solo a la base de datos "en vivo" (generalmente a través de inyección SQL), entonces es suficiente cifrar los campos usando algún secreto no almacenado en la base de datos, incluso alguna clave secreta codificada en el código de la aplicación o archivo de configuración. No hay necesidad de usar claves por cliente.
Si le preocupa que un atacante pueda acceder de alguna manera a los datos en su raíz web, pero no al resto del sistema de archivos (en general, si su servidor está mal configurado para permitir navegar por su contenido de la raíz web), nada cambia, después de todo, su servidor El código o el archivo de configuración deben estar fuera de la raíz web, ¿verdad? (Tengo poca experiencia con PHP, por lo que podría estar equivocado al respecto)
Si su preocupación es que un atacante se apodere de todo el sistema de archivos, debe asegurarse de que la clave solo exista en la RAM. Una forma de hacerlo sería requerir que se ingrese una contraseña en el servidor (re) start y mantener la clave derivada en una variable de acceso global (nuevamente, no sé si es posible con PHP). Puede haber otras opciones, pero cualquiera que pueda pensar introduciría otros puntos de falla. [1]
Estaba pensando en generar los certificados en el registro y utilizar parte de la huella de un certificado para cifrar los datos del usuario. por lo que la huella de SHA1 o MD5 podría funcionar como clave e IV.
Usar cualquier cosa del certificado es una mala idea, ya que los certificados son, por definición, públicos (las partes privadas nunca abandonan la máquina del usuario). Si de alguna manera podría hacer que el usuario descifre algunos datos con su clave privada (algo que AFAIK no está ampliamente soportado en este momento, pero podría ser en el futuro ), del lado del cliente, entonces podría estar tramando algo ... Pero tal como están las cosas ahora, simplemente podría crear una clave aleatoria para cada usuario y tener su código de aplicación léalo (desde un lugar seguro) y aplíquelo a los datos del usuario antes de ingresarlo / emitirlo.
Esto, por supuesto, supone que es necesario aislar los datos de un usuario de los otros usuarios. Si ese no es el caso, una sola clave global podría ser suficiente, como se describe en la primera parte de esta respuesta.
(una última nota: no ha mencionado el método que planea usar para cifrar los datos. Si está utilizando un cifrado de flujo, por ejemplo, no es suficiente tener un solo IV para cada usuario; debe tener una diferente para cada dato que desea proteger. No importa cómo los almacene, ya que no se supone que sean confidenciales, solo son únicos . Hay formas de crear un solo IV utilizable para cifrar una gran cantidad de datos , pero eso está más allá de mi conocimiento actual, así que no voy a opinar sobre ellos.)
[1]: Solo para nombrar uno, puede derivar una clave de cifrado a partir de la contraseña del usuario, almacenarla en una cookie de sesión (segura) y pasarla de un servidor a otro. Como no está almacenado en ningún lugar, un atacante no podrá acceder a él, incluso si se hizo con todo el servidor (suponiendo que su sitio sea correcto las contraseñas de sales and hashes y la clave de autenticación y la clave de cifrado son independientes entre sí ) . Para un poco de defensa en profundidad, incluso podría combinar esa clave con una almacenada solo en el servidor. El inconveniente obvio es que parte de la seguridad de su sistema ahora depende del navegador del usuario, y también de la forma en que se manejan las cookies de sesión tanto en el servidor como en el cliente.