Bcrypt relies on the blowfish cipher, which is a reversible method of encryption. But bcrypt is not reversible. How is that possible? Or am I mistaken? What does bcrypt do on top of blowfish to make it irreversible?
Using the psuedocode from the wikipedia article about bcrypt as an example:
bcrypt(cost, salt, input)
state ← EksBlowfishSetup(cost, salt, input)
ctext ← "OrpheanBeholderScryDoubt" //three 64-bit blocks
ctext ← EncryptECB(state, ctext) //encrypt using standard Blowfish in ECB mode
return Concatenate(cost, salt, ctext)
If you examine the main loop (the repeat 64 section), you can see that the hash input is being used as the key to the blowfish cipher in ecb mode, and is being used to encrypt the state. Then the ciphertext output of that encryption is used as the key to encrypt the state again, and again, until the repetitions are complete.
This means the output of bcrypt is essentially ciphertext output from the blowfish cipher. If you consider that the application of a strong cipher should effectively output pseudorandom data, this means the state is effectively being encrypted under a random key.
As long as the blowfish cipher is strong, ciphertext produced by it should be uninvertible without the key. Since the key was generated from the hash input, which is gone when the function call stack clears, the only way to regenerate the key is to know the hash input or find a collision.
Why does bcrypt use blowfish instead of twofish or threefish?
Only the designer could really answer this with absolute certainty, but I think that's a simple matter of when bcrypt was designed. Wikipedia says blowfish was published in 1993, and twofish in 1998, and bcrypt itself in 1999. While it appears twofish was available, it appears it was awfully new, which is considered an undesirable trait in cryptography. Threefish was first published in 2008, so was simply not available as a choice as it probably did not exist yet.