Would there be any problems using private/public key encryption for saving a password? - passwords

Using hashing algorithms like md5 we suffer from a limited entropy which means that very long passwords might result in hashes that can be regenerated by a shorter password.
I was thus wondering if it would be a good idea to store a password encrypted with the public key of public/private key encryption on the server. As decrypting is not needed, one could just throw away the secret key to avoid losing passwords when the server is compromised.
However, this method does not seem to be used widely. So are there drawbacks? If yes, then which?

There are several drawbacks. Among them:
You now have a token which must be protected. If someone gets your secret key, they have every password that was encrypted with that key. Asymmetric encryption is less of an issue if you "lose" the private key, but you better pray all copies of it are gone. Hashes can't be decrypted, period.
An encrypted password can be pretty much any length, and thus would require a pretty large field in the database (or length limits for the plaintext) in order to be stored. Hashes have a known length.
If you can decrypt the password, you know it. If ever there was a problem with someone using that password to break into something else, everyone who knew that password belonged to that user is a suspect. That now means you. Even if you use one-way encryption as a hash, you'd better be able to prove you can't decrypt it -- and then, if you don't want to decrypt it, why encrypt?
Generally, you'd only choose encryption over hashing when you have to know the password for something else -- like, say, when you're using it to log in to another system on behalf of the user. And ideally, you'd exhaust all other possibilities first.

Well there is always the drawback that computing a cryptographic hash is much less costly than encrypting a tiny password with a public-key encryption algorithm.
Secondly, you still suffer from limited entropy with public-key encryption, your bit string will still be limited. If you need more bits, use a hash with a bigger internal state (SHA-512, Whirlpool, etc...)
Third, you would need to store the public key along with the password, which results in a pretty hefty storage cost (considering how big public keys are), and if you're thinking of using the same public key for all passwords, don't - if that key is compromised it's over.
Also another consideration: without a password size limit there's a chance even padded block encryption will result in different storage sizes for different passwords, which can make database indexing a hell of a lot more difficult (probably not a huge concern but to keep in mind).
And finally, the biggie - hashes are meant to unequivocally destroy all structure in the input data, which is exactly what you want when storing passwords for verification. Encryption algorithms don't do that - they transform the data to make it unintelligible without the proper key, which sort of goes against what you're trying to use it for.
So, no, this method should not be used because it is self-defeating. Use a hash with a bigger internal state.

Related

Is it more secure to salt a string with a hash of itself?

So I've been looking at hashing passwords in vb.net and came across this thread (https://security.stackexchange.com/questions/17421/how-to-store-salt/17435#17435) and it showed about the salt only increasing the time to make brute force attack if the salt is known to the intruder as they need to make a new rainbow table. Could this be made more secure by making the salt a hash of the plaintext?
As an example to hash "plaintext" but adding a salt the string, this salt then being a hash of "plaintext" making "32nfdw213123" as example then hashing the total "plaintext32nfdw213123". In this case the salt is different for every value used but when used for verification doing the same process to a correct check string should produce the same salt and therefore the same hash value and verify. Is this actually more secure?
Thanks
TLDR: not really.
Longer answer:
Let's say some baddie has your database with all the passwords in it. He can now start brute-forcing passwords. Your goal is trying to make the brute-forcing as hard as possible.
So, theoretically, given that he has your database, he probably also knows how you're hashing your passwords (remember that security through obscurity is a bad form of defense). Your salts are no longer random, so our baddie can create a new rainbow table.

Is there an overall advantage to using a global secret key in addition to random item-level salts with bcrypt password hashing?

I use bcrypt for password hashing in php 5.3+
I understand that bcrypt uses a random salt that gets built into the resulting hash per item. This makes cracking each hash difficult, and prevents cracking
What I don't know is whether there still exists good reason to use an additional, application-level global secret key.
E.g. instead of just hashing a password string, e.g. "password1" into a bcrypt hash with the random salt that is built into the bcrypt generation system ( as per here: https://gist.github.com/1053158 ):
$2a$08$mjQAZ5cZi5B9u6zpUU4mGuRcvtxr1K.9ncYpxCdG.YhlD8yFG2mXK
I could also create a constant, e.g.: "##$%$%&BDFGG#$%BNG$Y^$%SEHYSZTHN$%" , put that constant into the application (either into the application source code or the application's configuration files), and append that to any string to be hashed.
So "password1"+"##$%$%&BDFGG#$%BNG$Y^$%SEHYSZTHN$%" -> would get hashed into a different hash from just "password1" alone.
$2a$08$xFgULsrpoIYlbxp1IG3H8.kdVggyhm4aTQXrP2Ptu25nMBUjBdrrK
Obviously in the context of the application itself, this doesn't help much. If someone tries the password "password1" on the running system, they'll succeed, because they'll automatically get the global secret key along for the ride. But if they have the database or access to the database only, it seems like the global secret key may be an additional obstacle? Because, not knowing the global secret key, they would have to crack ""password1##$%$%&BDFGG#$%BNG$Y^$%SEHYSZTHN$%" instead of just cracking "password1".
There are some potential benefits that may exist that I can imagine:
This might really hinder cracking the hashes using a compromised database alone?
And some vague disadvantages that may exist:
This introduces a common thread to all strings that get hashed, which may make it easier to crack hashes if it's known.
It increases the fragility of the data. If the global secret key is lost, e.g. during a server migration, or whatever, the data is now trash.
So I'm trying to figure out whether it's a good idea to also have a global secret key, or whether the random salt per item is both enough, and all you want. Does anyone know of any implementations that use a global secret key, or research that suggests using it?
The sole purpose of a salt is to defeat precomputation attacks (eg, rainbow tables). What you describe as a 'global salt' is, in fact, a secret key.
Opinions differ on whether this is useful. The only threat model it helps defend against is one where the attacker can get the contents of the database, but cannot access your source code. Personally, I'm of the opinion that this is a sufficiently narrow possibility that defending against it is unnecessary, and the amount of effort required to do it properly is unwarranted.
The purpose of salt and stretching is to make things hard for hackers to crack pwds if they access the database.
If you add an additional global salt in the app, then you are basically distributing your login process between app and db, which makes things more complicated than necessary and opens more venues to attacks.
What are you going to store in the db, the hash including the global salt or not? And then, what are you going to have to transfer between db and app during the login process? The communication should be secured between your app and the db anyway (otherwise your salting system can easily be broken with man in the middle).
There might be a tiny benefit if hackers only have access to db and never to app, but honestly, this is a very tiny non-realistic case today. Hacker will get access to your app before your DB. It is not worth the effort. Moreover, I may even be wrong.
Very often, people think of 'new' ideas when it comes to security, only to be smashed by hackers, because corner cases have not been identified and studied properly. It is a classic in cryptography. Thousands of those ideas have failed dramatically and cost those who used them a lot of pain. Creativity is a liability in cryptography.
Stick to the classic secured communications + random item-level salt scheme.

Can someone explain how to do password hashing + salting

I've read on SO (and from other websites found on Google after I tried to look into it a little bit more) that the correct secure way to store passwords in a database is to store the hashed + salted value of a password. On top of that, the salt should be different for each user so hackers can't do harm even if they have the encrypted values.
I'm not quite sure what salting means. From my understanding, you hash the password, then you use another value that you hash (the salt) and combine those two together so the algorithm to retrieve the original password is different for every user.
So basically, what I'd have to do is hash a password, then use a different hash on a different value for each user (ie: the user name or email address) and then I can do a simple math operation on those two values to get the encoded password.
Is that correct or did I just not understand anything about password hashing + salting?
A simple explanation or example would prove to be helpful as the sites I've found don't quite explain clearly what salting a password is.
Edit: After reading comments and answers left so far, I understand that I didn't really understand what a salt was because I'm missing some key concepts and I was making false assumption.
What I'd like to know is: how do you consistently get the same salt if it is randomly-generated? If the salt is stored in the database like some people have mentioned, then I can see how you keep getting the same salt, but that brings another question: How does it make the passwords more secure if anyone with access to the database have access to the salt? Couldn't they just append the (known) salt to all the passwords they try and the result would be the same (bar some minor time loss) than not having one at all?
Let me try and clarify a little bit with a somewhat oversimplified example. (md5() is used for example purposes only - you should not use it in practice.)
A salt is just a random string of characters that is appended to the password before it is hashed. Let's say you have the password letmein, and you hash it like this...
echo md5('letmein')
...you'll get the output 0d107d09f5bbe40cade3de5c71e9e9b7. If you google this, you'll get a number of pages telling you that this is the MD5 hash for letmein. A salt is intended to help prevent this sort of thing.
Let's suppose you have a function, randomStringGenerator() that generates a random $x-character string. To use it to salt a password, you'd do something like this:
$password = 'letmein';
$salt = randomStringGenerator(64); //let's pretend this is 747B517C80567D86906CD28443B992209B8EC601A74A2D18E5E80070703C5F49
$hash = md5($password . $salt);
You'd be then performing md5(letmein747B517C80567D86906CD28443B992209B8EC601A74A2D18E5E80070703C5F49), which returns af7cbbc1eacf780e70344af1a4b16698, which can't be "looked up" as easily as letmein without a salt.
You'd then store BOTH the hash and the salt, and when the user types in their password to log in, you'd repeat the process above and see if the password the user entered with the stored salt appended hashes to the same thing as the stored hash.
However! Since general hashing algorithms like MD5 and SHA2 are so fast, you shouldn't use them for storing passwords. Check out phpass for a PHP implementation of bcrypt.
Hope that helps!
One uses a salt to avoid the attacker creating a rainbow table, e.g. a table containing all (usual) passwords and the corresponding hashes, sorted (or somehow easily accessible) by hash. If the attacker has such a table or can create it, and then gets your password database with unsalted hashes, he can easily look up the passwords, even for all of your users at once.
If the hashes are salted (and the attacker gets the salt with the hashes), he will still be able to do the same attack (with only slightly more work to input the salt) - but now this work of building a rainbow table is useless for the next hash with another salt, which means this will need to be done for each user again. This alone is the goal of the salt. A dictionary attack on your single account still needs the same time as before, just the rainbow table is useless. (To do something against the dictionary attack, see below.)
How exactly the salt is used depends on the algorithm in use. Some hash algorithms (for example bcrypt, which is specially made for password hashing) have a special salt input parameter (or generate the salt themselves and include it in the output):
H = bcrypt(password, hardness) or H = bcrypt(salt, password, hardness)
(The first variant generates the salt itself, while the second takes it from the outside. Both include the hash and the hardness parameter in the output.)
Others need to be used in some special mode to use the salt.
A simple variant which works for most hash algorithms would be using HMAC, with the salt as "message" input, the password as key:
HMAC(password, salt) = Hash(password ⊕ opad || Hash(ipad ⊕ password || salt) )
where opad and ipad are some constant padding values.
Then you store the salt together with the hash. (For a slightly higher barrier, you could store the hash in another location than the salt. But you will still need both for login.) For login, you then will give the password and the stored salt to your hash function, and compare the result with the stored hash. (Most bcrypt libraries have a "password verification" function build in, which do this.)
For password storage it is important to use a slow hash algorithm, not a fast one, to avoid (or really: slow down) brute force or dictionary attacks on the passwords, as most people will have quite short passwords. bcrypt is an algorithm which was made just for this goal (its slowness is adaptable by a parameter).
If you use a fast hash function, be sure to repeat it often enough to be slow again. (But better, really: use bcrypt.)
Although #Chris and #Pualo have very good answers. I wanted to add one more thing about salting passwords that hasn't been expressed.
Salting a password is not a real protection mechanism. It doesn't matter if you are using bcrypt or any other mechanism. It is simply a delaying tactic, nothing more.
By using a different salt value per password you are forcing the hacker to create a rainbow table per password in order to crack them. This increases the amount of time it takes, but by no means does it make it impossible. Bear in mind that with cloud based computing you can spin up a large number of machines to create the rainbow tables and you can see that the delay is pretty small.
Further, most of the zombie machines out there are available for rent...
That said, the reason why you go through the trouble is to buy time. Time to notice that you've been breached, repair it and inform your users of the breach. That's it.
If an attacker obtained enough access to your database to pull the list of passwords, then it is pretty much guaranteed that they've obtained everything else. So, by this point you've already lost everything. The only question is how long does it take you to plug the hole, reset everyone's password and tell them that they should reset the passwords on any other account they may have where they used the same one. If you're Sony, then this time is apparently measured in months, if not years... ;) Try to be a little faster than that.
So, although it is the responsible thing to do it is only one part of your defensive tool belt. If you've been breached then you can bet those usernames and passwords will show up on a site somewhere at some point in the near future. Hopefully before then you've already cleaned up your house.
Using salt prevent precomputed rainbow-tables usage, as an example if a user use "Password" as a password, MD5("Password"), SHA1("Password"), or WhatEver("Password") may be well-known results stored in some rainbow tables.
If you use a different salt value per person - called a nonce - you'll get MD5(HMAC("Password","RandomSaltValue")), SHA1("Password","AnotherRandomSaltValue"), ... that mean two different hashed password values for the same initial password.
Now the question about storing these salts value...i think they can be stored into the database, the idea of salts are to prevent rainbow-style attack, not the database compromised issue.
Although bcrypt slows the process significantly down, it still would probably be feasible to attack your scheme if lots of computations can be made in parallel. I know it's unlikely and this would have to be a quite resourceful attacker indeed, but let's imagine the site you protect would contain photos and documents from Area 51 :) In that case, given enough parallelization, you could still be in trouble even if using bcrypt.
That's why I like the approach of scrypt - not only does it involve computational cost, but also it imposes memory constraints, specifically to introduce cost in terms of space and to make these kinds of parallel attacks infeasible. I can only recommend reading the paper that is linked on that site, it illustrates the concept really well.
Although, it seems that bcrypt and even more scrypt seem to get less attention in terms of cryptanalysis than PBKDF2outlined in RSA's PKCS#5. See this discussion for details.
I'd say first of all that security is very hard to do right, and that you really should rely on existing libraries to do as much as possible for you. For basic operations like password storage and validation that's definitely true.
EDIT: Removed erroneous info. I'll stick with the only good advice I had, which was not to roll your own.
What about Secure hash and salt for PHP passwords? It even has examples in PHP.

SHA1-hashing for web authentication in place of Blowfish

Being unable to locate a working php/javascript implementation of blowfish, I'm now considering using SHA1 hashing to implement web-based authentication, but the lack of knowledge in this particular field makes me unsure of whether the chosen method is secure enough.
The planned roadmap:
User's password is stored on the server as an MD5 hash.
Server issues a public key (MD5 hash of current time in milliseconds)
Client javascript function takes user password as input, and calculates its MD5 hash
Client then concatenates public key and password hash from above, and calculates SHA1 of the resulting string
Client sends SHA1 hash to the server, where similar calculations are performed with public key and user's password MD5 hash
Server compares the hashes, a match indicates successful authentication.
A mismatch indicates authentication failure, and server issues a new public key, effectively expiring the one already used.
Now, the problematic part is about concatenating two keys before SHA1, could that be prone to some kind of statistical or other attacks?
Is there any specific order in which keys should be concatenated to improve the overall quality (i.e. higher bits being more important to reliability of encryption)?
Thank you in advance.
If you're only using the 'public key' (which isn't actually a public key, it's a nonce, and should really be random, unless you really want it to be usable over a certain timeframe, in which case make sure you use HMAC with a secret key to generate it so an adversary cannot predict the nonce) to prevent replay attacks, and it's a fixed size, then concatenation might not be a problem.
That said, I'm a bit concerned that you might not have a well-thought-out security model. What attack is this trying to prevent, anyway? The user's password hash is unsalted, so a break of your password database will reveal plaintext passwords easily enough anyway, and although having a time-limited nonce will mitigate replay attacks from a passive sniffer, such a passive sniffer could just steal the user's session key anyway. Speaking of which, why not just use the session key as the nonce instead of a timestamp-based system?
But really, why not just use SSL? Cryptography is really hard to get right, and people much smarter than you or I have spent decades reviewing SSL's security to get it right.
Edit: If you're worried about MITM attacks, then nothing short of SSL will save you. Period. Mallory can just replace your super-secure login form with one that sends the password in plaintext to him. Game over. And even a passive attacker can see everything going over the wire - including your session cookie. Once Eve has the session cookie, she just injects it into her browser and is already logged in. Game over.
If you say you can't use SSL, you need to take a very hard look at exactly what you're trying to protect, and what kinds of attacks you will mitigate. You're going to probably need to implement a desktop application of some sort to do the cryptography - if MITMs are going around, then you cannot trust ANY of your HTML or Javascript - Mallory can replace them at will. Of course, your desktop app will need to implement key exchange, encryption and authentication on the data stream, plus authentication of the remote host - which is exactly what SSL does. And you'll probably use pretty much the same algorithms as SSL to do it, if you do it right.
If you decide MITMs aren't in scope, but you want to protect against passive attacks, you'll probably need to implement some serious cryptography in Javascript - we're talking about a Diffie-Hellman exchange to generate a session key that is never sent across the wire (HTML5 Web storage, etc), AES in Javascript to protect the key, etc. And at this point you've basically implemented half of SSL in Javascript, only chances are there are more bugs in it - not least of which is the problem that it's quite hard to get secure random numbers in Javascript.
Basically, you have the choice between:
Not implementing any real cryptographic security (apparently not a choice, since you're implementing all these complex authentication protocols)
Implementing something that looks an awful lot like SSL, only probably not as good
Using SSL.
In short - if security matters, use SSL. If you don't have SSL, get it installed. Every platform that I know of that can run JS can also handle SSL, so there's really no excuse.
bdonlan is absolutely correct. As pointed out, an adversary only needs to replace your Javascript form with evil code, which will be trivial over HTTP. Then it's game over.
I would also suggest looking at moving your passwords to SHA-2 with salts, generated using a suitable cryptographic random number generator (i.e. NOT seeded using the server's clock). Also, perform the hash multiple times. See http://www.jasypt.org/howtoencryptuserpasswords.html sections 2 and 3.
MD5 is broken. Do not use MD5.
Your secure scheme needs to be similar to the following:
Everything happens on SSL. The authentication form, the server-side script that verifies the form, the images, etc. Nothing fancy needs to be done here, because SSL does all the hard work for you. Just a simple HTML form that submits the username/password in "plaintext" is all that is really needed, since SSL will encrypt everything.
User creates new password: you generate a random salt (NOT based off the server time, but from good crypto random source). Hash the salt + the new password many times, and store the salt & resulting hash in your database.
Verify password: your script looks up salt for the user, and hashes the salt + entered password many times. Check for match in database.
The only thing that should be stored in your database is the salt and the hash/digest.
Assuming you have a database of MD5 hashes that you need to support, then the solution might be to add database columns for new SHA-2 hashes & salts. When the user logs in, you check against the MD5 hash as you have been doing. If it works, then follow the steps in "user creates new password" to convert it to SHA-2 & salt, and then delete the old MD5 hash. User won't know what happened.
Anything that really deviates from this is probably going to have some security flaws.

Replacing plain text password for app

We are currently storing plain text passwords for a web app that we have.
I keep advocating moving to a password hash but another developer said that this would be less secure -- more passwords could match the hash and a dictionary/hash attack would be faster.
Is there any truth to this argument?
Absolutely none. But it doesn't matter. I've posted a similar response before:
It's unfortunate, but people, even programmers, are just too emotional to be easily be swayed by argument. Once he's invested in his position (and, if you're posting here, he is) you're not likely to convince him with facts alone. What you need to do is switch the burden of proof. You need to get him out looking for data that he hopes will convince you, and in so doing learn the truth. Unfortunately, he has the benefit of the status quo, so you've got a tough road there.
From Wikipedia
Some computer systems store user
passwords, against which to compare
user log on attempts, as cleartext. If
an attacker gains access to such an
internal password store, all passwords
and so all user accounts will be
compromised. If some users employ the
same password for accounts on
different systems, those will be
compromised as well.
More secure systems store each
password in a cryptographically
protected form, so access to the
actual password will still be
difficult for a snooper who gains
internal access to the system, while
validation of user access attempts
remains possible.
A common approache stores only a
"hashed" form of the plaintext
password. When a user types in a
password on such a system, the
password handling software runs
through a cryptographic hash
algorithm, and if the hash value
generated from the user's entry
matches the hash stored in the
password database, the user is
permitted access. The hash value is
created by applying a cryptographic
hash function to a string consisting
of the submitted password and,
usually, another value known as a
salt. The salt prevents attackers from
building a list of hash values for
common passwords. MD5 and SHA1 are
frequently used cryptographic hash
functions.
There is much more that you can read on the subject on that page. In my opinion, and in everything I've read and worked with, hashing is a better scenario unless you use a very small (< 256 bit) algorithm.
There is absolutely no excuse to keeping plain text passwords on the web app. Use a standard hashing algorithm (SHA-1, not MD5!) with a salt value, so that rainbow attacks are impossible.
I don't understand how your other developer things 'more passwords could match the hash'.
There is argument to a 'hash attack would be faster', but only if you're not salting the passwords as they're hashed. Normally, hashing functions allow you to provide a salt which makes the use of known hash table a waste of time.
Personally, I'd say 'no'. Based on the above, as well as the fact that if you do somehow get clear-text expose, a salted, hashed value is of little value to someone trying to get in. Hashing also provides the benefit of making all passwords 'look' the same length.
ie, if hashing any string always results in a 20 character hash, then if you have only the hash to look at, you can't tell whether the original password was eight characters or sixteen for example.
I encountered this exact same issue in my workplace. What I did to convince him that hashing was more secure was to write a SQL injection that returned the list of users and passwords from the public section of our site. It was escalated right away as a major security issue :)
To prevent against dictionary/hash attacks be sure to hash against a token that's unique to each user and static (username/join date/userguid works well)
If you do not salt your Password, you're suspect to Rainbow Table attacks (precompiled Dictionaries that have valid inputs for a given hash)
The other developer should stop talking about security if you're storing passwords in plaintext and start reading about security.
Collisions are possible, but not a big problem for password apps usually (they are mainly a problem in areas where hashes are used as a way to verify the integrity of files).
So: Salt your passwords (by adding the Salt to the right side of the password*) and use a good hashing algorhithm like SHA-1 or preferably SHA-256 or SHA-512.
PS: A bit more detail about Hashes here.
*i'm a bit unsure whether or not the Salt should to to the beginning or to the end of the string. The problem is that if you have a collisions (two inputs with the same hash), adding the Salt to the "wrong" side will not change the resulting hash. In any way, you won't have big problems with Rainbow Tables, only with collisions
There is an old saying about programmers pretending to be cryptographers :)
Jeff Atwood has a good post on the subject: You're Probably Storing Passwords Incorrectly
To reply more extensively, I agree with all of the above, the hash makes it easier in theory to get the user's password since multiple passwords match the same hash. However,
this is much less likely to happen than someone getting access to your database.
There is truth in that if you hash something, yes, there will be collisions so it would be possible for two different passwords to unlock the same account.
From a practical standpoint though, that's a poor argument - A good hashing function (md5 or sha1 would be fine) can pretty much guarantee that for all meaningfully strings, especially short ones, there will be no collisions. Even if there were, having two passwords match for one account isn't a huge problem - If someone is in a position to randomly guess passwords fast enough that they are likely to be able to get in, you've got bigger problems.
I would argue that storing the passwords in plain text represents a much greater security risk than hash collisions in the password matching.
I'm not a security expert but I have a feeling that if plain text were more secure, hashing wouldnt exist in the first place.
In theory, yes. Passwords can be longer (more information) than a hash, so there is a possibility of hash collisions. However, most attacks are dictionary-based, and the probability of collisions is infinitely smaller than a successful direct match.
It depends on what you're defending against. If it's an attacker pulling down your database (or tricking your application into displaying the database), then plaintext passwords are useless. There are many attacks that rely on convincing the application to disgorge it's private data- SQL injection, session hijack, etc. It's often better not to keep the data at all, but to keep the hashed version so bad guys can't easily use it.
As your co-worker suggests, this can be trivially defeated by running the same hash algorithm against a dictionary and using rainbow tables to pull the info out. The usual solution is to use a secret salt plus additional user information to make the hashed results unique- something like:
String hashedPass=CryptUtils.MD5("alsdl;ksahglhkjfsdkjhkjhkfsdlsdf" + user.getCreateDate().toString() + user.getPassword);
As long as your salt is secret, or your attacker doesn't know the precise creation date of the user's record, a dictionary attack will fail- even in the event that they are able to pull down the password field.
Nothing is less secure than storing plain-text passwords. If you're using a decent hashing algorithm (at least SHA-256, but even SHA-1 is better than nothing) then yes, collisions are possible, but it doesn't matter because given a hash, it's impossible* to calculate what strings hash to it. If you hash the username WITH the password, then that possibility goes out the window as well.
* - technically not impossible, but "computationally infeasible"
If the username is "graeme" and the password is "stackoverflow", then create a string "graeme-stackoverflow-1234" where 1234 is a random number, then hash it and store "hashoutput1234" in the database. When it comes to validating a password, take the username, the supplied password and the number from the end of the stored value (the hash has a fixed length so you can always do this) and hash them together, and compare it with the hash part of the stored value.
more passwords could match the hash and a dictionary/hash attack would be faster.
Yes and no. Use a modern hashing algorithm, like an SHA variant, and that argument gets very, very week. Do you really need to be worried if that brute force attack is going to take only 352 years instead of 467 years? (Anecdotal joke there.) The value to be gained (not having the password stored in plain text on the system) far outstrips your colleague's concern.
Hope you forgive me for plugging a solution I wrote on this, using client side JavaScript to hash the password before it's transmitted: http://blog.asgeirnilsen.com/2005/11/password-authentication-without.html