0

How best to use the encryption method for confirm code on email notification: md5, sha1 or sha256

I make email notification for confirm some actions by email;

I generated confirm code with salt and some parameters.

How best to use the encryption method for confirm code?

frops
  • 2,196
  • 4
  • 29
  • 42
  • 1
    Refer this link - http://stackoverflow.com/questions/2593807/md5uniqid-makes-sense-for-random-unique-tokens – ejo Jun 21 '13 at 08:57
  • the security depends on what your using as the input to generate the hash, for example if your using the `REMOTE_ADDR` then anyone can guess it. – DevZer0 Jun 21 '13 at 08:58

2 Answers2

2

You have two main options here:

  1. generated some random data, store it in your database associated with that profile, and put only this data on the link;
  2. generate some kind of secure hash based on, say, the user id, and then pass both the user id and that hash on the link

The first option is secure (supposing you are using either a real random number generator or a very, very good pseudo-random number generator), but you have to store data on a database.

I usually prefer the second option, since there's no need to store anything on a database, and no need to query the database to check if the link is valid.

Choose a secret key that only your server will know, then define exactly what parameters you want to validate in the URL (for instance, only the user id might be enough; however if you want the link to expire, you could add a timestamp to the url and validate both the user id and the timestamp with your hash). Mix your secret key with the parameters, generate a hash based on this, and create a link specifying both your parameters and the hash. When the user clicks the link, you take the parameters from the url, combine them again with the secret key, hash the result and compare with the hash that came with the url.

A secure way to do this is to use HMAC, which is Hash-based Message Authentication Code. See: http://php.net/manual/en/function.hash-hmac.php.

Note that this mechanism exposes the data you are validating in the url. If the data is secret (ie, suppose you want to send the link to the user containing both the username and his password, without saving anything at all on the database before he clicks the link), you must use Authenticated Encryption, which is a mix of an encryption algorithm (which guarantees that no one can read the data) and an authentication algorithm (which guarantees that no one can temper with the encrypted data to produce something meaningful -- only your server is able to generate such code).

Bruno Reis
  • 37,201
  • 11
  • 119
  • 156
  • As your answer rightly explains, the second approach involves a lot of careful planning, and is easy to get wrong (as complexity is the enemy of security). It raises the question of whether it's worth all the effort, particularly when considering that by far most sites with users already have some sort of a database. That database could be used for the first approach. – ntoskrnl Jun 22 '13 at 09:13
  • Isn't HMAC a one side encryption? how do I decode it back to plain string? – Volatil3 Nov 24 '15 at 08:30
  • HMAC is not a type of encryption algorithm, it's a MAC algorithm. You don't "decode it back to plain string", that's the nature of MAC algorithms. Also, I'm not sure what you mean by *"one side encryption"*. – Bruno Reis Nov 24 '15 at 08:36
0

If you're just generating a "random" confirmation code, you don't need to worry about which hash function you're using; you don't really care about the security of the hashed information, just in the non-guessability of the confirmation code. This means that the more bits of entropy, the more secure (and unique) your confirmation code will be. MD5 results in 128 bits of entropy, SHA1 in 160 bits, and SHA256 in 256 bits. Use a big salt (>= 1024 bits should be fine) and call it good.

If you want it to be really secure, then read n bytes (where n is some large number, 24+) from /dev/random or /dev/urandom (the former only if you're running something like egd, otherwise you're potentially susceptible to DOS attacks) and hex- or base64-encode them, store them on your user record, and set that as your confirmation code. This completely eliminates guessability and doesn't have a single point of attack like a common pepper would.

Chris Heald
  • 61,439
  • 10
  • 123
  • 137
  • Do I need to still use salt and additional parameters, or you can just do use md5(uniqid(rand(), true)) ? – frops Jun 21 '13 at 09:16
  • 1
    Using a hash function does not increase the entropy of the data at all – it just spreads it over a specific length. You should just read bytes from a secure random number generator. See this: http://stackoverflow.com/questions/1182584/secure-random-number-generation-in-php – ntoskrnl Jun 21 '13 at 09:24
  • So, I have to generate a random sequence of characters? – frops Jun 21 '13 at 09:30
  • @ntoskrnl From a guessability perspective, the length of the output hash is the effective entropy, so long as the input length is greater than the hash output length, which is why I recommended a big salt. – Chris Heald Jun 21 '13 at 09:36
  • 1
    @frops Don't use rand() if you care about actual randomness; it's deterministic and attackable. Read from a secure random number generator; /dev/random is generally good enough. – Chris Heald Jun 21 '13 at 09:37