Create a strong password scheme when all data is stored on the device

Background:
I was working on an Android application that stores data in a local database as my favorite project. Recently, I decided that I want to password protect the application and encrypt the database. Now I know about the complexities of database encryption on the fly and (given the expected usage model of my application) decided to simply encrypt the entire database file, rather than trying to save the encrypted column value or the like. So far, I have implemented a system that will ask for a password every time the application starts or whenever the user switches from my activity (to take into account that the user presses the home key and the application does not kill in a timely manner).

I'm currently trying to decide how to hash the password and where to store it. Given that everything should be stored on the device, I mainly consider hashes of passwords and salts that have already been compromised, since anyone who has spent 10 minutes reading can connect this device and gain access to my database / preferences.

I have developed something that I think will still provide very strong security, given the above assumptions. I wanted to get feedback from the community to find out if my solution is viable or if there is a better way.

My idea is to generate 10 different values โ€‹โ€‹of random salts the first time I run the application. These values โ€‹โ€‹will be saved with the actual final password hash in the application settings (and not in the database). Please note that there will be only one password, and it is used both for user authentication and for decrypting the database. Whenever a call is provided, the password will be hashed as follows:

  • Password Cleartext hashed.
  • The Hashed password is triggered through the same checksum algorithm that is used for standard UPC barcodes. This will result in a value between 0 and 9 (inclusive).
  • This checksum digit will be used as an index for an array of salt values. This is the only salt value to be added to the current hash.
  • A new hash value + salt will be added, and steps 2 through 3 will be repeated.

I believe that this process for 5 iterations would give 5 ^ 10 different salt combinations alone and should make any type of rainbow attack virtually impossible. After the final hash has been verified correctly, it can be used to decrypt the database.

Now I understand that this sounds like overkill for a simple mobile phone application. It. But, this is my favorite project, why not?

Question:
So, after this wall of text, is this approach reasonable or is there a better way? I think with this in place the weakest link would be an attack in memory, or am I mistaken? Any feedback is greatly appreciated.

Thanks in advance.

-cheers

+4
source share
5 answers

I do not understand. If you are encrypting the database, why do you need to store the password hash anywhere?

Derive the encryption key from the password, which is stored in the user's brain, using something like PBKDF2. Use it to encrypt the database.

When the user wants to decrypt the database, request them for a password. Derive the key from it again and decrypt the database.

You save a password hash for authentication purposes. But this is encryption, not authentication.


Suppose you have a hash function that takes salt, iteration count and password as input and returns a hash as output: byte[] hash(byte[] salt, int count, char[] password) . Randomly generate one salt the first time you launch the application and the hash is the new password. Save this salt and the resulting hash in the application settings. Then randomly generate another salt and hash the password with it. Use the resulting hash as the database encryption key, but save only the new salt in the application settings.

Later, when the user wants to use the application, suggest a password and use the first hash salt. If it matches the stored hash, the user has proven that he knows the decryption password. Repeat it with the second salt and use the obtained key to decrypt the database.

This subsequent output of the encryption key may be what you meant; I am trying to make this step explicit if you intend to use the password directly as the encryption key. Having two different salts, one for authentication and one for encryption, allows you to safely use the same password for both purposes.

+5
source

I use the database row entry id as salt. You can use the string identifier and use it for salt salt.

If you only have a dozen or so passwords, it seems a bit like security, what you already do. But if you have hundreds or tens of thousands, it becomes impossible to calculate one dictionary table for each identifier.

0
source

Good ... Assuming your hashing method is not weak, it doesn't matter if the salt is known. The salt is just that 2 users with the same password have different hashes - and randomly checking the hashes will not make identical passwords obvious. The salt must be unique to each user.

Assuming that the user (malicious) has a root, absolutely nothing can be done to prevent their application from being compromised, except for encryption - in particular, the user could theoretically get your binary file, decompile it to determine how it authenticates users, bypasses it, and then just follow the decryption mechanism. And since the encryption key is not associated with a custom PW in your script, it must be saved by SOMEWHERE - and if the application can read it, so root

The only truly secure approach would be to have a single-user (or at least one single) password associated with the database encryption key.

In addition, the best you can hope for is to make it difficult enough for a malicious user that he is not worth his time.

0
source

Even with 10 salt values, you are still technically vulnerable to rainbow tables . All they need to do is create 10 rainbow tables, each of which uses your salt. For some time they will need to generate all new rainbow tables, we say days or weeks. When they have tables, they can use it for all users downloading the application. If you keep a unique salt for the password, which will require them to go through the entire process for each password, which is very important for just one password. The question is, will someone want to go through all these problems to get one password. Here is a good article about storing passwords "You may not store passwords correctly"

0
source

I do not see any serious weakness in this scheme. However, it does not add any safety to salting best practices; that is, generate a new salt for each user each time the user sets or changes his password.

This scheme adds an extra attack. If there is a weakness in the fact that salts are generated (for example, predictability), then it will probably be easier to use if you limit yourself to 10 salts, all generated at the same time. This can give an attacker more leverage to guess what the probable salts are, and therefore create rainbow tables.

But the main problem with your approach (IMO) is simply complexity.

0
source

Source: https://habr.com/ru/post/1332157/


All Articles