Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

Alright, so I understand that users are the kind of beasts who like to use one password and make it short and easy to remember (like "doggies"). If I understand correctly, that's one reason we use password salts. They add length and some level of randomness. My problem is how to generate them. The way I've been generating my salts (and the password hashes) in a recent (still entirely in-house) project is to do the following:

  1. Grab the time in seconds since the epoch
  2. Grab the time the process has been running (as granular as the OS allows)
  3. Create the MD5 hash of both results above
  4. Append the 4 strings I now have in a varying combination
  5. Store this as plaintext
  6. Append the password and salt in a few ways
  7. SHA-512 hash that to create the password hash

Is this sufficiently random? Does it add enough entropy? I recently read I need a stronger hashing algorithm (looking at bcrypt) and need multiple hashes (1000+) to be safe enough, but that's not the focus of the question.

share|improve this question
1  
one thing to note is that algorithms like bcrypt should handle the complexity around salts and hash interation for you. you can specify a work factor to increase the interations. for python there's some more info. here mindrot.org/projects/py-bcrypt –  Rоry McCune Dec 12 '12 at 9:55
add comment

2 Answers

up vote 15 down vote accepted

This seems misguided.

Time in seconds from any source lacks almost any entropy, and is almost immediately guessable. If your OS allows microsecond granularity for a running process, you'll get 4 or 5 bits of entropy there, from the lower bits, but a lot less if someone finds a way to get the exact system uptime.

You're then talking about MD5, which isn't really useful in this case. All it does it give you the impression that you've made it more random, without actually making it random. Really you've only got a couple of integers that are dependant on each other (process time is always going to be in sync with system uptime) and that are entirely non-random. Your system will almost certainly leak its uptime in one form or another. You'd actually be better off using an LCG like PHP's rand(), since the internal state can't be guessed as easily.

This approach to random number generation is bad, because it's not random at all, and can be predicted. However, salts don't actually need to be particularly random, they just need to be unique; they're only there to prevent rainbow table attacks. Unpredictability helps (see "how to store salt?") but isn't entirely required. Regardless, there are some benefits to making the salt difficult to predict.

If you're on Linux, read some bytes from /dev/urandom to generate the salt - you don't need to do anything more than take those bytes and use them, because they're already strong random numbers.

If not, you could generate the salt as SHA256(username || email || time || mt_rand()) where || denotes concatenation, time is the current system time in as high a resoluton as you can get, and mt_rand() is an output value from whatever random generator is available in your programming language's default library. In PHP you should use mt_rand rather than rand, since it has better characteristics. This provides enough entropy for a salt to be very difficult to guess remotely, especially given the limited opportunities for re-use of username and email combinations.

For storing the password, you should definitely be using PBKDF2 or bcrypt. A single use of a cryptographic hash function is simply not enough to protect you from bruteforce attacks, especially when almost everyone has an OpenCL-compatible GPU these days.

share|improve this answer
1  
Are you using || as OR or concatenation? –  Nakaan Dec 12 '12 at 7:07
    
Concatenation. Sorry, should've specified that. In general for security, though, you'll see people use || to mean concatenate, and | to mean a bitwise OR operation. –  Polynomial Dec 12 '12 at 7:09
    
Ah, okay. I would have expected + or . haha. Anyway, I'm building this in Python (with the planned release to be Windows) and have never looked into the random number generation facilities of it (no need until now). Salts ARE stored in plaintext, right? –  Nakaan Dec 12 '12 at 7:12
1  
Yup, store them in plaintext. No need to obfuscate them, since they're not really meant to be secret information (though it helps in certain cases; see the answer I linked). They're just there to make pre-computed rainbow table attacks infeasible. –  Polynomial Dec 12 '12 at 7:14
    
Just an aside - here's a short story about secret salts from RFC 5869: It is worth noting that, while not the typical case, some applications may even have a secret salt value available for use [...]. An example of such application is IKEv1 in its "public-key encryption mode", where the "salt" to the extractor is computed from nonces that are secret; similarly, the pre-shared mode of IKEv1 uses a secret salt derived from the pre-shared key. –  Henning Klevjer Dec 12 '12 at 7:15
show 8 more comments

Actually, a salt needs not be random; it needs to be unique. This is worldwide uniqueness (unique for all times and for all servers around the world), and the easiest way to achieve uniqueness is to use randomness: generate 16 bytes (or more) with a cryptographically strong random generator, and the probability that you hit a salt value which has already been used elsewhere is sufficiently small to be neglected.

Randomness is hard. What you present is the combination of a homemade weak random number generator, and a homemade weak password hashing mechanism. The proper way to generate a salt is to ask the system pseudorandom number generator to do it for you (/dev/urandom on Unix-like systems, CryptGenRandom() on Windows, System.Security.Cryptography.RNGCryptoServiceProvider on .NET...). Then, use the salt with a proper password hashing system like bcrypt or PBKDF2. Most bcrypt implementations will actually do the salt generation for you, so that's even better.

share|improve this answer
    
I know you know what you mean, but I would say the easiest way to achieve uniqueness is to use randomness is a pretty misleading/incomplete statement. –  lynks Dec 28 '12 at 17:15
    
@lynks: OK, I added some more explanations. –  Thomas Pornin Dec 28 '12 at 17:35
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.