Tuesday, April 23, 2013

Randomize the Elements of an Array

Sometimes it is useful to be able to randomize the elements of an array and this posting will demonstrate a simple way of accomplishing that using the shuffle subroutine of the List::Util Perl module.  As a sample use case let’s consider a simplistic random password generator that was designed to generate passwords that contain two uppercase characters, two numbers, and four lowercase characters. A sample code snippet that would accomplish such a task might look as follows:


use List::Util 'shuffle';
use strict;
use warnings;

#Ensure number of each character type requirements are met
my @randuc=map{('A'..'Z')[rand(26)]}(1..2);
my @randlc=map{('a'..'z')[rand(26)]}(1..4);
my @randnum=map{int(rand(10))}(1..2);
my @pass=(@randuc, @randlc, @randnum);
my $passwd=join("", @pass);
print "$passwd \n";

If executed, this code would create random passwords such as “SEadzs55”, which clearly meet the complexity requirements, but if we run the password generator over and over again a pattern should emerge.  The two upper case characters will always be first, followed by the four lowercase characters, followed by the two numbers.  This pattern greatly reduces the randomness of our passwords and is a common mistake you see in many random password generators.  We could greatly improve this code by adding some additional code that will randomize the elements of the password, so there is no definitive pattern as to the ordering of characters.  We could do this with the following code snippet:

#Shuffles the generated characters so uc characters not always first
#followed by lc characters, etc to improve randomness
my @mixed = shuffle(@pass);
$passwd=join("", @mixed);

print "$passwd \n";

If we now execute the code with this addition multiple times, will see that after each execution the ordering of the characters is randomized, thereby improving the entropy of our password. 

No comments: