Dividamos esto en dos:
Encriptando los datos del usuario con su contraseña
Claro, por qué no, si los datos son privados. En la práctica, el servidor necesitará manejarlo en texto sin formato, pero los datos pueden dejarse encriptados mientras el usuario no haya iniciado sesión. Aunque en un foro de mensajes, los mensajes que deben ser leídos por otros usuarios no pueden estar sujetos a este tratamiento, por lo que prácticamente solo funciona para mensajes privados (dirigidos a un solo usuario o un grupo conocido de usuarios).
Como siempre, no desea usar ninguna contraseña directamente como clave, sino ejecutarla a través de alguna función de derivación de claves como PBKDF2 . Esto ralentizará la búsqueda de la contraseña por fuerza bruta y dará la posibilidad de generar claves más largas que la contraseña (en caso de que sea necesario).
En cuanto a los cambios de contraseña, la práctica habitual es generar una clave segura aleatoria, utilizada para cifrar los datos, y luego almacenar esta clave cifrada con (una clave basada en) la contraseña del usuario. De esta manera, cambiar la contraseña solo requiere volver a cifrar la clave maestra, no todos los datos.
Aunque el inconveniente aquí siempre es que si el servidor está comprometido, puede configurarse para guardar la contraseña del usuario en texto sin formato la próxima vez que inicie sesión, o simplemente guardar todos los datos sin cifrar.
Encriptando todos los datos con la clave del servidor
Aquí, me pregunto cuál es la amenaza esperada? ¿Un ataque de software que pierde toda la información (encriptada) o que el hardware del servidor se pierde? La protección contra el hardware fuera de lugar requeriría el cifrado de los datos con una clave que no se encuentra en el propio sistema , sino que tal vez se ingrese manualmente. La forma más sencilla de hacerlo sería utilizar alguna solución de cifrado de disco completo.
En cuanto a un ataque que de alguna manera filtra todos los datos, pero no permite que se modifique el código, seguro, el cifrado con una clave de servidor fija debería ayudar. Pero, ¿necesita hacerlo si los datos ya están cifrados con la clave del usuario? ¿Qué tan factible es que los datos encriptados se filtren pero no la clave del servidor, dado que el servidor va a necesitar esa clave para casi todas las operaciones relacionadas con los datos? Tengo que decir que no lo sé.
(Si está pensando en inyecciones SQL, corrija mejor sus prácticas en eso donde está el problema. Por otra parte, si está pensando en una vulnerabilidad que conduce a la ejecución de código arbitrario, el atacante acaba de obtener la clave del servidor , también.)
Combinando los dos
La forma obvia de combinar dos claves sería cifrar los datos dos veces, utilizando ambas claves, de modo que los datos almacenados sean C = E (K2, (E (K1, P)). Esto es lo que sucedería en el finalice si almacena datos encriptados en una unidad encriptada, pero es un desperdicio o trabajo.
Otra forma sería derivar la clave de cifrado real de las dos claves (servidor y usuario) utilizando un KDF (nuevamente). Aunque con entradas de apariencia aleatoria, creo que podría salirse con la combinación de dos claves de longitud fija con un hash fuerte como SHA-256, por lo que C = E (H (K1, K2), P).