# Can SHA256 hash be considered as a secure key proof?

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:

1. Brute force password - since we are using slow hashing function (PBKDF2) and at least 40-bits of entropy passwords, it will take years.
2. 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?

• what is stopping the hacker from just sending the hash? Why does he need to know the key anyway? Commented Apr 23, 2021 at 0:08
• You need a nonce. Send them a random string. They send back sha256(key + random string). This requires they have the key, not just sha256(key). en.wikipedia.org/wiki/Cryptographic_nonce Commented Apr 23, 2021 at 0:44

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.

How does that prove that client (who may be pretending to be the user) knows the key? He obviously knows SHA256(key), but he might have gotten that from the real user.

Even if the negotiation between the client and the server was encrypted (which you do not specify), one obvious approach for an adversary to get that value is to pretend to be the real server, and have the client attempt to log in (and that client will send that SHA256(key) value as a part of the exchange).

• Hum, yes, as proof it would not work, only as identifier. For proof you'd sign a nonce or similar construction, e.g. in a challenge response protocol. Commented Apr 22, 2021 at 20:09
• @MaartenBodewes: or possibly use a PAKE (Password Authenticated Key Exchange, examples: SRP, EKE, CPACE or Opaque, for those who aren't up with the latest crypto acronyms) Commented Apr 22, 2021 at 20:13

SHA-256 is commonly used for fingerprinting or for calculation of key check values (KCV's) even in Hardware Security Modules (HSM's). As the hash is a one way function it should be secure. However, that's only used to identify keys, not to proof that you have the key.

One thing to worry about is if the key is used for other purposes that include hashing. In that case you might run into issues with domain separation. In that case you could think of using a HMAC or KDF calculation instead, using a (presumably) unique string as input message (next to the key).

And yes, as always, the PBKDF is more vulnerable than the hash calculation for the check value. You'd be right to focus on that.

Poncho points out that it is important to understand what constitutes a proof of knowing the password. So that answer is important.

Beyond that, you're specifically concerned with the ability to find a pre-image for SHA256 given that you know the pre-image comes from a low-entropy source run through PBKDF2.

If you think about it, the case you are worried about is not an issue with SHA256, but rather with PBKDF2. If you can take advantage of the low-entropy source (the password), that implies that you can distinguish the output of PBKDF2 from a random oracle. I believe this would constitute "breaking" PBKDF2. The output would be distinguishable from a random oracle.