The short answer
DO NOT DO THAT. It is not secure.
The long answer
There are three main types of attacks against password based systems:
- Guessing (e.g. birth date of the person, wife's name, etc.)
- Brute force - trying all possible inputs
- Dictionary attacks
To prevent an outside attacker (somebody NOT having access to your web server, just the public interface of it), the best way is to slow down the login, also implement counters per user, e.g. lock out the user for 5 minutes after 5 tries, and send a notification to the user in email.
However, this does not protect you from attacker having access to your password database, e.g. due to a breach your password database is leaked. It is quite possible, just think about Yahoo!, eBay, Adobe, etc.
Why "naked" hash function is not secure?
To show the problem, let's say user has a password "apple123".
encrypted_password = sha1("apple123")
encrypted_password will be "ec1e7fb8656dba32737acabc2e5a1fb2d02a973f".
Now search for this hash. What you will see, is the password. How? Did Google cracked SHA-1?
Obviously not. There are tons of dictionaries out there, in which Google searches. And believe me, there are much-much better ones, than what is published to the web.
The only limit you may think, is the storage what a "good" dictionary would require. Well, there are techniques to significantly reduce the storage of a dictionary (meaning - millions of times), using a technique called Rainbow tables. I will not go into the details of if, overly simplified it is a heavily compressed password/hash dictionary.
Another thing to note, that once the password database is leaked, an attacker has also the possibility to brute force, by calculating the SHA-1 of each possible combinations. Takes time, but with GPUs it
How to protect against dictionary attacks?
If you have a good rainbow table or other compressed dictionary, it is created for one specific hash function. So, the idea to protect against rainbow tables is creating multiple hash functions - millions, billions of hash function, by adding a public random, called salt.
salted_password = sha1("apple123 s6589fvj3e785s72o57zd8934sncag4")
The salt need to be random, and different for each users. So, you need to store the salt in the password database, next to the salted_password, and once the user submitted the password, you should calculate the salted version.
I would suggest using HMAC_SHA_256 for this purpose, with 256 bit random salt.
How to protect against brute force attacks by using CPUs?
The idea is to artificially slowing down the hash function by "stretching", on top of salting, by introducing lot of iterations. The naive implementation is
stretched_password = HMAC_SHA_256(salt, HMAC_SHA_256( salt, HMAC_SHA_256( ..., "apple123"))...)
DO NOT use the naive implementation, use PBKDFv2 instead of that, which has protection against CPU parallelization and pre-computation as well.
How to protect against brute force attacks by using GPUs?
Unfortunately, simple streching is not enough, when a simple computer can have tens of thousands of processing units - called GPU based password cracking. To slow down the GPUs there are large pseudo-random memory maps are used for the calculation, because GPU processing units have very-very slow individual access to the memory. bcrypt or scrypt provide protection against such attacks.
Any further protection
The very best is using Password Authenticated Key Exchange, or PAKE, in combination with scrypt. I personally prefer SRPv6 and AugPAKE, but there are other protocols as well.
If you are interested on a fully implemented, secure authentication, you may consider using 0_kit, a project I am involved in.
The bottom line
If you want server only, logic, go with scrypt.
The next chart shows the reason why: the question is not how fast can you break the password anymore, because you can build a huge GPU farm and do it obviously faster than using 1 CPU. Colin Percival created a nice calculation (in 2009!), how much would it cost you to break a password in 1 year.
If you want to go a bit further, use SRP or AugPAKE, but that would require client side logic as well.
If you want to have secure password authentication, all of that implemented off-the-shelf, consider using 0_kit, a project I am involved in.