Encrypt Files in DocumentsDirectory (SQLITE DB)

Hello,

I have a app that uses a DB (SQLite3) to store a lot of information, including sensitive data from users that can connect to the app using facebook for instance.

I need that Database to be protected somehow, either by encryption or password protecting, but it cannot be accessed easily like it is now by just connecting a device (iPhone/iPad) to a PC/MAC and accessing that directory (system.DocumentsDirectory).

Or, if none of that is possible for some reason, does anyone know any “workaround”, like putting that database in another folder or something?

This was the main problem (a very serious one): a tester here easily “impersonated” another user on the app because the app has a Config table on said database that “registers” the login information (email, name, userid, etc.) so the users dont have to login every time they open the app.

Thanks in advance.

What you ask is impossible to achieve.

If the user has root on the device, he will be able to inspect the contents of your app package (including decompiling it) and the memory used by the application while it’s running. (The solution, which does not help you today, is if Apple and Google ever started building TPM cryptoprocessors into the hardware with a Corona-supported API.)

The best you can do is obfuscation. Take the email, name, userid. Obfuscate before saving to sqlite. Deobfuscate when reading. See previous discussion here:

http://forums.coronalabs.com/topic/54991-secret-data-in-the-lua-code/

To encrypt something you need a key. To store a key, you need a secure storage. There is no secure storage on the device, so your only secure option is to store the key in the mind of the user. Make the user choose a strong password, and use it to encrypt the contents of the database. The user will have to input the password every time they want to access the data, of course… but if you want to make the solution secure, that’s the way.

As corona273 says, you can also attempt to obfuscate your data, which makes it more difficult to read - enough to stop someone who doesn’t know what they’re doing, but probably not enough to stop a skilled attacker.

Another approach could be to use a unique hash derived from the deviceId as a factor for the encryption key for that particular device. That way, everytime the app is installed onto a new device, you have a unique encryption key. 

Since deviceId is available at code level, your eventual encryption key could be a combination of : Hash of (a random string in the DB generated during install time + a random string generated during install time and stored in a file in documents directory + a hash derived from deviceId)

At the very minimum, it prevents users from impersonating others without knowing the encryption logic inside the code (needing code decompiling) and the user device’s unique ID.

Hope this helps. 

Hello,

Thanks for the replies. I aint going to persue any of those methods (for now), because in my case I think I should actually go “around” this problem in a whole different manner, which is not putting any of that data on the local DB and only on a remote DB. That means that now some part of my app can only be viewd with Internet connection on the device instead of not needing it, but its a small price to pay for the much better security without need to worry about encryption/decryption of the data.

Ill bookmark this thread for future reference though, thanks.

What you ask is impossible to achieve.

If the user has root on the device, he will be able to inspect the contents of your app package (including decompiling it) and the memory used by the application while it’s running. (The solution, which does not help you today, is if Apple and Google ever started building TPM cryptoprocessors into the hardware with a Corona-supported API.)

The best you can do is obfuscation. Take the email, name, userid. Obfuscate before saving to sqlite. Deobfuscate when reading. See previous discussion here:

http://forums.coronalabs.com/topic/54991-secret-data-in-the-lua-code/

To encrypt something you need a key. To store a key, you need a secure storage. There is no secure storage on the device, so your only secure option is to store the key in the mind of the user. Make the user choose a strong password, and use it to encrypt the contents of the database. The user will have to input the password every time they want to access the data, of course… but if you want to make the solution secure, that’s the way.

As corona273 says, you can also attempt to obfuscate your data, which makes it more difficult to read - enough to stop someone who doesn’t know what they’re doing, but probably not enough to stop a skilled attacker.

Another approach could be to use a unique hash derived from the deviceId as a factor for the encryption key for that particular device. That way, everytime the app is installed onto a new device, you have a unique encryption key. 

Since deviceId is available at code level, your eventual encryption key could be a combination of : Hash of (a random string in the DB generated during install time + a random string generated during install time and stored in a file in documents directory + a hash derived from deviceId)

At the very minimum, it prevents users from impersonating others without knowing the encryption logic inside the code (needing code decompiling) and the user device’s unique ID.

Hope this helps. 

Hello,

Thanks for the replies. I aint going to persue any of those methods (for now), because in my case I think I should actually go “around” this problem in a whole different manner, which is not putting any of that data on the local DB and only on a remote DB. That means that now some part of my app can only be viewd with Internet connection on the device instead of not needing it, but its a small price to pay for the much better security without need to worry about encryption/decryption of the data.

Ill bookmark this thread for future reference though, thanks.