I am concerned about the use of bcrypt for client-side password generation. I am developing a password generation function to be used client-side, similar to PwdHash and PasswordMaker.
Much has been said about the advantage of using bcrypt over faster hash functions because it slows down brute force attacks. I know bcrypt uses Blowfish internally, which is a symmetric encryption algorithm rather than a hash algorithm. So there must be a hard-coded key somewhere to use bcrypt, and since Blowfish is being used, it stands to reason that if the key is discovered, the password derivation can be reversed and the original password discovered.
Since client-side code can be decompiled, the key could be easily discovered, making bcrypt unsafe to use client-side. Is my reasoning correct or have I missed something?
Also, in a related question, wouldn't the same argument be valid server-side as well. A hash function cannot be reversed, but an encryption function can be if the key is known. Wouldn't it be safer to use a real hash server side, even if it is faster and therefore more susceptible to brute force attack, than to use bcrypt which is reversible?
EDIT: user10008 notes below (post has been removed) that only parts of Blowfish are used in bcrypt and gave me a link. When I followed a link I found a function prototype that includes key as the last argument. So I still see the key being used to kick-start the bcrypt algorithm. If the key is required, and bcrypt uses symmetrical encryption instead of hashing, isn't the operation reversible?
EDIT: Good answers from both martinstoeckli and user10008. I gave the answer to marginstoeckli because of the last sentence in the response:
BCrypt can be seen as encrypting with throwing away of the key.
This really cleared it up for me. Basically, we go through 2 phases
P -> K ; P,K -> C
and then throw away key K, leaving cyphertext C. Because we throw away the key K, we cannot decrypt back to plaintext P. Throwing away K effectively makes bcrypt a one-way function.
EDIT: From user10008, the steps I gave above are more complex, however the essence is that the key K is used in the final phase and discarded. Thanks user10008.
P -> K; "OrpheanBeholderScryDoubt", K -> C
, orP -> K; K -> C
, if you add the constant into the function. Also perhaps an explanation to your comment to my answer.