2

I know that there are alots of questions about this subject but i really need to ask this.

Today I've been working on encrypting passwords with md5.

So what I've done is.

I got 4 salts. (they changes depending on user values)

  1. from email id and substr then md5 them
  2. from email and id substr other positions
  3. a long string, substr it and then md5 it
  4. another long string, substr it and then md5 it

Then i md5 salt1 and 3 and the password with salt 2 and salt4

After this I have to change the password automatically whenever a user changes his email or his id getting changed.

What do you guys think about this?

Kilise
  • 1,051
  • 4
  • 15
  • 35
  • 3
    Don't roll your own crypto-scheme. Use well-tested and -analyzed systems such as [`crypt`](http://php.net/crypt), which also offer a variable number of rounds. – knittl Jan 26 '13 at 14:53
  • 1
    You might as well pass the salts through a blender :) – Gigi Jan 26 '13 at 14:53

6 Answers6

14

Nothing.

MD5 is broken and bad.

Using the mailaddress as salt is a good idea. But using md5 is not. Use instead bcrypt, scrypt or pbkdf2.

Don't invent your own ecryption, unless you really know what you are doing, and trust me, you don't

Fabian Blechschmidt
  • 4,113
  • 22
  • 39
  • So what it can do is just change md5 to hash or something else? – Kilise Jan 26 '13 at 14:57
  • use bcrypt http://stackoverflow.com/questions/4795385/how-do-you-use-bcrypt-for-hashing-passwords-in-php The question is, how high should the costs be? If you ask me, so high, that your server needs 500ms-1sec to calculate the hash. http://en.wikipedia.org/wiki/Bcrypt – Fabian Blechschmidt Jan 26 '13 at 15:03
  • 1
    Using the mail address is not a good idea for salting, because the salt should be unique for EVERY hash. So, if the user were to change his password, a new salt should be created. – Edwin Jan 26 '13 at 15:06
  • Well I have already made that the salt changes when his email is gettting changed Doesn't it solve everything then? – Kilise Jan 26 '13 at 15:10
  • @edwin normally a mailaddress is unique in the system, so using this as salt means a unique salt for every password. – Fabian Blechschmidt Jan 26 '13 at 16:42
  • 1
    @FabianBlechschmidt If the user changes his/her password a new hash would be created using the same salt. Plus, an attacker could pre-create hash tables with guessed email addresses that could be used on multiple sites I guess this is nit picking, but to me, that's what crypto is: paying great attention to the seemingly inconsequential. – Edwin Jan 26 '13 at 17:07
  • Years later I recognize what you said @Edwin. You are totally right. email adress solves lots of the points a salt should do, but using a random one, makes precomputation even harder. – Fabian Blechschmidt Jan 20 '17 at 00:00
8

First, let us define a few terms.

  • Encryption is when you encode a message so that it cannot be read. Encryption involves a plaintext, a cipher and a key. It is like putting a book (the plaintext) in a locked room (cipher), which can only be opened using a known tool (a key). There are many kinds of encryption, but that is a simple description. Encryption is two-way, meaning that you can encode and decode the message.

  • Cryptographic hash is when you take any kind of data and generate a fixed size value for it (usually called a hash or a digest). Cryptographic hashes are one-way, which means that you cannot reverse the process.

  • A salt is a unique string, or a collection of bits, similar to a nonce (a unique number that is only used once). Salts are only used to make it infeasible for a cracker to process a list of hashes. They are not supposed to be used as a secret (i.e. like a cryptographic key). The only reason people usually talk about randomness when it comes to salts is because they want to generate a unique salt (if the randomness is not great enough they may get colliding salts, for instance).

Okay, now to how you should hash a password.

A relatively safe way of hashing a password is to simply tack on a unique hash onto a password, and then save the salt with the password:

$pass = 'this is my password';
$salt = uniqid('', true);
$hash = sha1($pass . $salt);
// INSERT INTO users ('hash', 'salt') VALUES ('$hash', '$salt') WHERE ...

That is an okay way of doing it if your website does not retrieve any sensitive data from its users.

If you deal with sensitive data, or if you just want to make sure that you are doing everything you can to keep stuff safe, then there is a PHP function that does the hashing for you. It is called crypt() (read the documentation to learn how it works). Here is an example of how to hash a password using the function:

$pass = 'this is my password';
$salt = 'unique string';
$hash = crypt($password, '$2y$07$'.$salt.'$');
echo $hash;

That will securely hash a password.

The thing to realize is that the crypt() function is much more secure than anything you can come up with (unless you are a specialist in the area).

In newer versions of PHP (5.5.0+) there is a password hashing API that makes it even simpler to hash a password.

There are also various hashing libraries out there. PHPass is a popular one.

Sverri M. Olsen
  • 13,055
  • 3
  • 36
  • 52
  • You should always use a salt with the `crypt()` function. Be sure to read the documentation thoroughly before using the function, though. It works in a slightly odd way where the salt needs to be prepended with various information. – Sverri M. Olsen Jan 26 '13 at 16:20
  • 2
    "That is an okay way of doing it if your website does not retrieve any sensitive data from its users." NO it is not. Users reuse there passwords. You have to make sure, that if you database is hacked, the passwords are not bruteforced. Most of the passwords are built with an easy algorithm, including the name of the website (in best case). But often you can login with the password into twitter, facebook or paypal! – Fabian Blechschmidt Jan 26 '13 at 16:45
  • @Sverri M. Olsen: do you realize what `07` from your answer (`$2y$07$`) means? Isn't it related to "don't double hashing"? – zerkms Jan 29 '13 at 04:24
  • @zerkms It is not double hashing, it is key stretching/strengthening used to make cracking infeasible. – Sverri M. Olsen Jan 29 '13 at 06:05
  • @Sverri M. Olsen: "it is key stretching/strengthening" --- by using what? Rounds, which are in fact loops. I will even quote the manual for you "The two digit cost parameter is the base-2 logarithm of the iteration count". Thoughts? – zerkms Jan 29 '13 at 06:28
3

It is bad, because it uses MD5.

MD5 is a very fast operation. It can be executed billion of times per second on graphic cards hardware. It is considered bad practice to use it for any password related things.

Use bcrypt. Use a random salt. Use the upcoming PHP API for hashing, verifying and rehashing passwords. This include file implements it for versions starting with PHP 5.3.7: https://github.com/ircmaxell/password_compat

Sven
  • 69,403
  • 10
  • 107
  • 109
  • I could just change md5 to hash or something else, and keep my salts by userid and emails and random strings? – Kilise Jan 26 '13 at 15:01
  • 1
    Read the documentation: You simply call `password_hash()` with the password to create a new hash. You call `password_verify()` with the users password and the stored hash to see if it is correct. You can optionally check whether the hash has to be updated because you made some changes to the hashing configuration. – Sven Jan 26 '13 at 15:06
  • Your hashing scheme is very obscure: it is unlikely that someone would guess how you created your hashes. However, if someone got a copy of your algorithm and your passwords, then it would be simple to reverse the hashes back to plain text. Like @Sven said, MD5 is too fast to prevent this attack. A good crypto scheme (bcrypt, etc) takes a long time to work, so even if your passwords are stolen (and the hashing scheme is already known), it would be impractical to try to reverse the hashes. – Chris Jan 26 '13 at 15:11
  • Does it really matter how obscure the scheme is? The salts are getting substringed then hashed. then they're getting hashed with the password in an other scheme. So it would be secure. And ofcourse it would be simple if someone got a copy of the algorithm. Correct me if I'm wrong – Kilise Jan 26 '13 at 15:17
  • Why bother with creating and updating hashes and salts when you can have the best security for free with the library I suggested? – Sven Jan 26 '13 at 15:19
  • I haven't said I wouldn't use the library you sent me , it looks good. Just want to get updated about the encrypting things and why my salts wouldn't work good. (I now know md5 is bad.) – Kilise Jan 26 '13 at 15:23
  • A salt should be unique per password and long to prevent pre-calculation. Your scheme uses the mail address, which is not long. It's about 10 to 20 chars, and consists of human-readable stuff like user's and domain's names. – Sven Jan 26 '13 at 15:38
  • " and consists of human-readable stuff like user's and domain's names." --- how human readability affects on salt quality? – zerkms Jan 29 '13 at 02:19
  • It's more predictable than truly random salt. – Sven Jan 29 '13 at 02:27
  • @Sven: so why didn't you just mention predictability? Readable doesn't mean it's predictable. Goodluckwithpredictingsuchstring. The worst thing is when one names not the root of the issue (like "predictability" here), but the consequences, and newbies start blindly following it. Yep, be sure, after you comment some people will think that "readability" here is the key factor. – zerkms Jan 29 '13 at 04:26
2

Well, "MD5 is broken and bad" is a little exagerated. Even if it can be brute-forced with a lot of CPU, it is not "broken" and is still a very useful algorithm for a lot of things involving hashing.

So "MD5 should not be used for password encryption" sounds much better to me.

When using PHP, an easy and safe option is to rely on the password_hash() (which natively generates a random salt) and password_verify() functions.

The advantage is that the encryption algorithm will transparently be updated with each new PHP version (at the moment PASSWORD_DEFAULT is set to bcrypt, but should bcrypt be "broken" it can be set to a newer algorithm), which makes any code using those functions quite resilient.

Cédric Françoys
  • 870
  • 1
  • 11
  • 22
-2

I personally do not recommend involving of the user id and his email into the hashing of his password. You can deal with the password by:

  • Dynamic salt per user based on random string generated on user registration
  • Prepend one part of the salt and append the other around the password
  • Double md5: md5(md5($password))
  • Etc.
Plamen Nikolov
  • 2,643
  • 1
  • 13
  • 24
  • No, sorry. Using MD5 is bad. Doubling it will take you nowhere. – Sven Jan 26 '13 at 14:55
  • The salt just needs to be unique, randomness is beside the point; how the salt is applied makes little difference; and double hashing can make things LESS secure. – Sverri M. Olsen Jan 26 '13 at 14:58
  • Yes indeed but the user is asking about md5, I personally do not recommend using it but in case he does not have PHP 5.3+ or mcrypt installed he can use at least SHA1... – Plamen Nikolov Jan 26 '13 at 14:58
  • MD5 is in your answer - that can be seen as a recommendation. You haven't suggested anything else lableded "better". – Sven Jan 26 '13 at 14:59
  • So i could change md5 to another encrpyt function and keep my salts (changing their md5 too) ? what do you think about that? – Kilise Jan 26 '13 at 15:04
  • @Sverri M. Olsen: "and double hashing can make things LESS secure" --- any details on that? – zerkms Jan 29 '13 at 02:14
  • @Sverri M. Olsen: there is exactly the same "even make the hashes less secure" without explanation WHY it does it less secure. So, it doesn't count. Any other *real* references/explanations? – zerkms Jan 29 '13 at 04:28
  • @zerkms I am open to being corrected. So, if you think I am in the wrong then explain to me why I am wrong. Rebuffing statements with questions is a waste of everyone's time. – Sverri M. Olsen Jan 29 '13 at 06:23
  • 2
    @Sverri M. Olsen: you said that it's LESS secure, not me. You're spreading the information you cannot prove. Why do you think it's correct? If someone writes something without proofs - it doesn't mean you should trust it. Security is a terrible precise thing: if something is stated - it may be and should be proven, otherwise it's a bullshit. – zerkms Jan 29 '13 at 06:29
-2

a simple way would be to generate a random salt for each user and hash your password like this

public function encodePassword( $raw, $salt ) {
    return hash('sha256', $salt.$raw);
}

For high security hash, you can check this link which explain how to implement PBKDF2:

http://crackstation.net/hashing-security.htm#phpsourcecode

julien rollin
  • 1,607
  • 1
  • 12
  • 17