We want to generate strings that can be used as passwords (storing later will be done with ex.: bcrypt, but these are the literally meant passwords).

On a Linux machine, the two generation methods are:

head -c 8192 /dev/urandom | md5sum | cut -d' ' -f1
head -c 8192 /dev/urandom | tr -cd '0123456789abcdef' | cut -c-32

Which method provides "more security"? Are there any slight difference between the two outputs?

I'm thinking that the second one could be better, since it is "truly random".

The first one with md5 (imho) cannot be better than the second one since it uses a hash, that could have collisions (with a very low chance, but it could have).

[user@notebook ~]$ head -c 8192 /dev/urandom | md5sum | cut -d' ' -f1
[user@notebook ~]$ head -c 8192 /dev/urandom | tr -cd '0123456789abcdef' | cut -c-32
[user@notebook ~]$ 

So both have the same length, both use the same available characters, both have the same random inputs.

I recently read that there are random generators based on hash: Hash-DRBG so not sure.

Of course pwgen could be used to generate passwords, but the question is that which of these two generating methods are more secure?

If the question is not 100% clear, I can adjust it, just ask please.

  • 3
    $\begingroup$ All this faffing about seems completely unnecessary to me. Why not simply fetch 16 bytes from /dev/urandom and convert them into hexadecimal (head -c 16 /dev/urandom | xxd -p)? $\endgroup$ – r3mainer Dec 18 '16 at 22:25

It looks like you're attempting to jump through weird hoops just to encode raw bytes as hex. You're just using md5sum because of its side-effect of hex output, and worse, you're sending 8192 random bytes through tr and blindly hoping you get 32 hex characters from it.

Why not just encode 32 random bytes directly into 16 hex octets?

head -c16 /dev/urandom | xxd -p
  • 1
    $\begingroup$ -1. This isn't superuser, this is crypto. While your answer isn't wrong, you don't mention enough about crypto aspects, instead you focus on commands used (which I hope were only used to demonstrate rather than show anything else). $\endgroup$ – axapaxa Dec 18 '16 at 22:57
  • 1
    $\begingroup$ Then apply your -1 to the question, which in practice has nothing to do with crypto other than an confused attempt to use the md5sum command-line tool as a way to hex-encode a raw byte stream. $\endgroup$ – Stephen Touset Dec 19 '16 at 1:35

The ideal password would be:

  1. Secure: Randomly drawn with equal probability from a sufficiently large set;
  2. Usable: Easy for a human being to memorize and input into their device.

These two goals are at odds, but that's a story for another day. For your question, then, you need to answer what components of your proposals are contributing to those two goals, and which are just superfluous. And looking at it:

  • /dev/urandom makes random choices with equal probability, and the number of bytes you read from /dev/urandom puts bounds on the size of the set from which those random choices are made. So pulling enough bytes from /dev/urandom will fulfill #1 on its own.
  • The output of /dev/urandom is random bytes that are hard for humans to memorize and input. So you need a method to convert those random bytes into a user-friendly alphanumeric string. The only real requirement for that method is that it produce a sufficient number of distinct outputs, and that any of those outputs is equally likely as all the others.
  • md5sum isn't contributing anything to security here. All it's really doing is converting the random bytes to a hexadecimal string, in a convoluted (but otherwise acceptable) way. That, coupled with the fact that MD5 is a broken hash function, is a big code smell.
  • Drawing 8,192 random bytes to drop all those that aren't ASCII hexadecimal digits is a crassly inefficient way to produce a random hexadecimal string. It also has a non-zero probability of producing fewer than the 32 hex digits that you're aiming for. Why not just draw 16 random bytes and encode them to hex directly?

So a big simplification of your proposals is the command that Stephen beat me to:

% head -c16 /dev/urandom | xxd -p

One possible improvement, following my #2 from above, would be to use a more compact binary-to-ASCII encoding, like Base64 (with the trailing = signs deleted):

% head -c16 /dev/urandom |base64 |tr -d '='

Next improvement: just make the passwords shorter so that people don't have to type as much. If you just draw 10 random bytes the passwords have 80 bits of entropy, which is much stronger than the passwords most real-life users choose.

% head -c10 /dev/urandom | base64 |tr -d '='

And another improvement, which helps only in the memorability front, would be to encode the random bytes as random passphrases, like in Diceware or the famous XKCD comic.

Note that my final recommendations—using 80 bits of entropy instead of 128—are, in strict numerical terms, less secure than what you started with proposing. But the key philosophical point here is that the design only needs to be secure enough, and as long as a reasonable target security level is met there's no gain from going beyond it. If anything, the longer passwords needed to achieve "greater" security are harder to use. But security at the cost of usability often comes at the cost of security.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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