Cifrado de datos dentro de la base de datos SQLite en Java - ¿Cómo almacenar la clave?

4

Por lo tanto, un poco de contexto antes de comenzar puede ser útil. Estoy desarrollando una aplicación de escritorio Java que utilizará una base de datos SQLite para almacenar / procesar datos. La aplicación utilizará la autenticación para acceder al programa para editar datos, agregar / eliminar datos, etc. Pero no quiero que un atacante pueda extraer el disco duro de la computadora portátil y acceder a los datos sin autenticar primero en Windows.

Mi pregunta es, si tuviera que cifrar ciertos datos antes de insertarlos en la base de datos SQLite con, digamos ... AES256, ¿es posible descifrar los datos sin que el usuario tenga que insertar una contraseña Y sin codificar la contraseña en la aplicación? ? Realmente creo que la sobrecarga de que el usuario tenga que recordar 2 contraseñas (una para la autenticación de la aplicación y otra para el cifrado / descifrado de la base de datos) es inviable porque si olvidan la contraseña de cifrado / descifrado, sus datos desaparecen.

¿Alguno de ustedes ha encontrado alguna solución que pueda compartir o sugerir algunas ideas que puedan ser de ayuda?

    
pregunta Anthony N 17.07.2014 - 17:39
fuente

1 respuesta

7

Cuando el usuario inicie sesión por primera vez, su software le pedirá una nueva contraseña. En este momento el DB debe estar vacío.

Ahora tienes un UserPassword y una base de datos vacía. Por lo tanto, el software genera una nueva DBdataKey aleatoria que se utilizará para cifrar / descifrar el contenido de la base de datos. Para cifrar / descifrar utilice uno de los muchos algoritmos conocidos, como AES o uno similar.

Ahora creas 2 cadenas de sal aleatorias: PasswordSalt y DBdataKeySalt . Almacene PasswordSalt y DBdataKeySalt en la base de datos como un texto claro.

Use una función hash como pbkdf2 (o algo como SHA2 o superior) con UserPassword y DBdataKeySalt para obtener un DBdataKeyEncryptionKey

Ahora: DBdataKey es la clave que utiliza para cifrar / descifrar el contenido de la base de datos DBdataKeyEncryptionKey es la clave que utiliza para cifrar / descifrar la DBdataKey

Use una función hash como pbkdf2 (o algo como SHA2 o superior) con UserPassword y PasswordSalt para crear HashedSaltedUserPassword , un hasted salh versión de UserPassword , luego use DBdataKey para cifrar HasedSaltedUserPassword antes de almacenarlo en la base de datos.

De ahora en adelante, puede utilizar DBdataKey para cifrar / descifrar los datos desde / hacia la base de datos.

Ahora, cuando el usuario abre la aplicación, pídale la contraseña, luego use la contraseña ingresada con DBdataKeySalt (que se almacena en texto claro) para regenerar la DBdataKeyEncryptionKey , y luego usa el DBdataKeyEncryptionKey para descifrar el DBdataKey , y así puedes usar el DBdataKey descifrado para leer el DB.

Ahora use DBdataKey para descifrar el HashedSaltedUserPassword y compárelo con el que regeneró usando la contraseña ingresada y el PasswordSalt (que es almacenado en texto claro) solo para verificar que la información de inicio de sesión sea correcta.

Si el usuario ingresa la contraseña incorrecta, cuando use DBdataKeyEncryptionKey para descifrar la DBdataKey , la función de descifrado le dará un valor diferente (basura). Usar ese valor (incorrecto) para descifrar el HashedSaltedUserPassword dará como resultado más valores de basura, que no coincidirán con el hash.

Cuando el usuario cambia la Contraseña del usuario , solo necesita descifrar la DBdataKey con la contraseña anterior y volver a cifrarla con la nueva contraseña, pero la DBdataKey no cambiará, por lo que no tendrá que volver a cifrar el contenido de la base de datos cuando el usuario cambie su contraseña.

Referencia: No he inventado nada, esto es solo una mezcla de dos técnicas bien conocidas:

respondido por el Max 24.07.2014 - 21:21
fuente

Lea otras preguntas en las etiquetas