Effective Perl by Joseph N. Hall

Observations and Tips from the author of Effective Perl Programming

Monday, January 30, 2006

Tip: Creating a String of Random Hex Digits

Every once in a while a string of random hex digits comes in handy*, perhaps when you need a random alphanumeric name for something. The unpack operator seems like it should come in handy for this purpose, given that it can translate character values into hex strings, and so it does. Here's a snippet that creates a string of 32 random hex digits:

my $rand_hex = join "", map { unpack "H*", chr(rand(256)) } 1..16;

rand(256) produces floating-point numbers 0.0 <= n < 256.0. unpack "H2" turns a character (a single-character string to be precise) into a 2-character MSB-first hex string - the chr is needed to turn the numeric value from rand into a string. The map { ... } 1..16 creates a list of 16 different 2-character strings, and join gloms them all together.

Here's another - simpler - way to generate 32 random hex digits:

use Digest::MD5 qw(md5_hex);
my $rand_hex2 = md5_hex(rand);

*Or maybe you think that Perl looks like random hex digits all on its own. Most people, however, think it looks like modem line noise $$817 d3#@ ss NO CARRIER

4 Comments:

At 8:30 PM, Anonymous Anonymous said...

md5_hex(rand) will not give you a string of random hex digits. In fact, it's considerably less than random, since rand() gives 32, 48, or 64 bits of randomness, but a md5 hash is 128 bits. So there are 2^128 possible md5 hashes but your md5_hex(rand) will choose from only at most 2^64 of them. So it only looks random -- be careful!

 
At 9:02 PM, Blogger Joseph N. Hall said...

Of course it's a random string. However, it doesn't have 128 bits of entropy.

It's also unlikely that glomming together hex digits resulting from repeated calls to rand will really produce 128 bits of randomness - because the pseudorandom number generator on your favorite platform is probably not cryptographically strong.

 
At 1:20 AM, Anonymous Anonymous said...

my $0,2

perl -e 'print ((0..9,a..f)[rand(16)]) for 1..32'

 
At 8:09 PM, Anonymous Wicked Web Programmers said...

Thanks.You can always run your Perl code under Perl's w flag.

 

Post a Comment

<< Home