Making a one-way function harder to reverse Let's suppose that for a crypto protocol a 32-byte-to-32-byte one-way function is needed. Proposals are:


$\textrm{sha256}(x)$
$\textrm{hmac}(\textrm{sha256}, x, x)$
$\textrm{hmac}(\textrm{sha256}, x, f(x))$, where $f$ is a 32-byte-to-32-byte function whose inverse is easy to compute, e.g. bytewise reverse (whose inverse is itself).


Are #2 and #3 any harder to reverse than #1 (plain SHA-256)? Is there an even harder to reverse proposal?

I understand that if the attacker has access to a generic method with which it's possible to reverse any 32-byte-to-32-byte function, then #1, #2 and #3 are equally easy to reverse, and thus they are equally secure.

Let's suppose that in the future someone finds a fast way to compute the inverse of SHA-256 on 32-byte inputs, but there is no other fast generic reversing method is available. (The attacker is highly motivated to reverse SHA-256, because doing so can possibly break many crypto protocols.) This doesn't help finding the inverse of #2 or #3, because they have an outer SHA-256 call whose input is 64 bytes.
(2) and (3) are expected to cost slightly more to invert than (1), no matter what the distribution on $x$ might be, because the only known preimage search algorithms treat them as black boxes to be evaluated forward and search more or less by guessing and checking (optimized with rainbow tables or quantum computers).

The expected cost of any such algorithm is the cost of evaluating the function, times the expected number of times you must evaluate it.  The cost of evaluating (2) and (3) is the same, but they both cost about twice what (1) costs.  You can make things much costlier by using a modern password hash such as scrypt or argon2.

However, if the only possible values of $x$ are the strings red and blue with equal probability, then the difference in cost is negligible.  The adversary has a 50-50 chance of getting it right in one try.

So a much more important question is: How are you using this in your application?  How does it fit into the protocol?  What security properties do you hope to achieve by it?  What costs do you hope to impose on an adversary trying to break the system?

If the distribution on $x$ has >=128 bits of entropy, or if there are actually two inputs of which one is a secret with >=128-bit entropy and the other maybe has low entropy, there's no reason to try to raise the costs of evaluating the function by iterating SHA-256 or using scrypt or argon2.  On the other hand, if you're storing password hashes, then you should absolutely use something designed for password hashes that raises the area*time cost and thwarts attackers with high levels of parallelism.