I want to use PBKDF2 with 1,000,000 iterations (I don't know yet exactly how many I will choose) to derive a 256-bit symmetric key K from a password provided by a user (at least 40 bits of entropy). Then I would like to have a proof that the user has/knows the key K. The key will be hashed once with a SHA256 function and the result H will be stored in a database (SHA256(key)). So, whenever I will need to verify that the user has the key K, it will be hashed on frontend and only the H value will be sent to the server, so I can compare it with the value stored in DB. The key will never leave a user's computer.
Let's say a hacker wants to find out what the 256-bit key is. There are two ways:
- Brute force password - since we are using slow hashing function (PBKDF2) and at least 40-bits of entropy passwords, it will take years.
- Try to find out the key by attacking from "the other side". So, the hacker will need to find a preimage, thus key K of the hash H. As we know SHA256 is one-way function, so it is nearly impossible.
The question is: are there any possible vulnerabilities in this solution? I know that finding a 256-bit random preimage of SHA256 is not possible, but we are not dealing here with a "true" 256-bit value generated by a cryptographically secure random number generator. The 256-bit key K we are dealing with is in fact derived from a user password which entropy is much, much lower, let's say only 40 bits.
What I understand is that from the perspective of a second attack we can treat the key K as a true 256-bit value because we have to find out the exact 256-bit value. We don't need to worry that it was derived from a source with 40-bits entropy. We have to worry about this only in the first scenario, so that's why I want to use a slow hashing function.
Conclusion: it is more likely the key K will be found by following the first way of attack than the second one, thus this only one SHA256 hashing round is secure. If I want to make the entire solution more secure I should consider more PBKDF2 iterations or the PBKDF2 should be replaced with a better function (like Argon2). Am I right?