There is a couple of ways to create a random password with shell/bash. For instance, we can just pipe the date command to md5sum or sha256sum to generate a seemingly random string that can be used as a password:
date | md5sum
71192e8f893e41e54f5356716c81a2de -
date | sha256sum
11d1d0e43bd5ab65e2c7d14505856562213339f852f0195e3b53a9418babf5d0 -
That is a start. If we don’t want the whole string, when can trim the result with head:
date | sha256sum | head -c 10; echo ' '
The 10 after -c tells head to show the first 10 characters. However, this is not the best approach for several reasons. When it comes to passwords, a lot of services, websites and applications request the use of special characters, upper-case and lower-case letters. Also, date is not a random value (or at least not a pseudorandom number). A good way to generate a random number for a password is to use /dev/urandom. The man command for urandom reads “the random number generator gathers environmental noise from device drivers and other sources into an entropy pool”. Piping /dev/urandom to head, we can see how it works, but now we have the opposite problem: a bunch of symbols and characters that are not accepted for most passwords. With that in mind, we need to find a way to get rid of that: tr. This command allow us to “translate or delete characters”. So we will need to take the input from /dev/urandom and sent it to tr. For that, we’re going to use the -d and -c options available for tr. According to the help, those options can do the following:
- -c to “use the complement of SET1“
- -d to “delete the characters in SET1“
If we combine both options we are telling tr to do the following: first use the complement of SET1 (the complement of a set A… are the elements not in A), and then because of -d we want to “delete the characters in SET1”. But since we are also telling tr to use the complement of SET1 instead of SET1, that means we are getting rid of everything that is not in the SET1 and that is exactly what tr is going to do. Next thing is to define the SET1 of characters we want to be part of the resultant string. After that, we want to send the output of /dev/urandom to tr and for that we have the STDIN redirection symbol: <. Let us join all this in way that allows us to call a bash script with the parameters of the password we want. Something like this:
#!/bin/bash
pComplexity=$1
pLength=$2
charSet=""
if [[ -z "$pLength" ]];then
pLength=10
fi
if [[ $pComplexity == 1 ]]; then
charSet="A-Za-z"
elif [[ $pComplexity == 2 ]]; then
charSet="A-Za-z0-9"
elif [[ $pComplexity == 3 ]]; then
charSet='A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~'
else
charSet='A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~'
fi
tr -dc $charSet </dev/urandom | head -c $pLength;echo ''
pComplexity and pLength receive a value from positional parameters when the script is called. If the script was called without parameters, pLength is going to have a value of 10. On the other hand, the default complexity of pComplexity is going to be 3. There is three levels of complexity:
- Uppercase letters and lowercase letters
- 1 plus numbers
- 2 plus especial characters
pLength determines the amount of characters in the resultant password. To run this script we need to modify the permissions of it to allow execution (chmod +x) and then call the script:
./passwordGenerator.sh
{I5u3^!bXv
Now a couple of examples with parameters:
./passwordGenerator.sh 1 15
WGXtMchibgYkEJB
./passwordGenerator.sh 3 20
?5*dOR1$H09xc4g]]NDY