Linux has its own cryptographic generator which can easily be harnessed by the common user to generate extremely strong passwords. This password generator can be found at /dev/random. /dev/random generates pseudorandom numbers based on the available entropy of the system (see wiki page). A derivate of /dev/random called /dev/urandom does the same thing but it is more accessible while being slightly (theoretically) less secure. So what stops us from grabbing outout from /dev/urandom using cat? An output of the content of /dev/urandom will demonstrate that it is practically gibberish with very few usable random characters. The output of
should convince the user. However, it is possible to trim out the unwanted characters and only keep alphabets, numbers, and special characters with a simple filtering by the tr command.
This command will produce the desired output but it will generate very small passwords, which are truly random but which do not meet the length criteria in most cases. Therefore, this procedure needs to be repeated a large number of times until the required length of random passwords can be generated. It is better to write a bash script which will automate this procedure.
The following bash script generates random passwords and allows the user to control the length and number of random passwords that are generated. It also allows special characters to be included or excluded with a switch (argument). Since I am always in a hurry and don't like passing too many arguments, I wrote the script so that it can accept arguments in a shorthand manner in addition to the longhand manner (Unix style) of passing arguments. Shorthand way: ./randompass.sh 10 2 1 will generate 2 random passwords of length 10 and they will all include special characters.
Or I could use the longhand (Unix-style) way of passing the arguments: ./randompass.sh -l 10 -n 2 -s 1
The result will be the same. I have included the full code below which is well commented. I also provide explanation and cite sources below the code.
cat /dev/urandom
should convince the user. However, it is possible to trim out the unwanted characters and only keep alphabets, numbers, and special characters with a simple filtering by the tr command.
cat /dev/urandom | head -c 10 | tr -dc "A-Za-z0-9_!"
This command will produce the desired output but it will generate very small passwords, which are truly random but which do not meet the length criteria in most cases. Therefore, this procedure needs to be repeated a large number of times until the required length of random passwords can be generated. It is better to write a bash script which will automate this procedure.
The following bash script generates random passwords and allows the user to control the length and number of random passwords that are generated. It also allows special characters to be included or excluded with a switch (argument). Since I am always in a hurry and don't like passing too many arguments, I wrote the script so that it can accept arguments in a shorthand manner in addition to the longhand manner (Unix style) of passing arguments. Shorthand way: ./randompass.sh 10 2 1 will generate 2 random passwords of length 10 and they will all include special characters.
$ ./randompass.sh 10 2 1 ST5%l36HpG 4Tvq%Ia1UZ
Or I could use the longhand (Unix-style) way of passing the arguments: ./randompass.sh -l 10 -n 2 -s 1
$ ./randompass.sh -l 10 -n 2 -s 1 IofK1_qA%l %5aw_YY1XZ
The result will be the same. I have included the full code below which is well commented. I also provide explanation and cite sources below the code.
#!/bin/bash # generate random passwords using urandom CSPRNG. # randompass.sh v5.2 by Jones # ---- SET INITIAL VALUES ---- length=16 num=4 special=1 usage=" Usage: ./randompass.sh [options ...] -l password length. DEFAULT=16 -n number of passwords to generate. DEFAULT=4 -s special characters. DEFAULT=1. Set to 0 to disable selecting _!% -h help Example 1: ./randompass.sh -l 8 -n 2 -s 0 OR ./randompass.sh [password length] [number of passwords to generate] [include special characters] Example 2: ./randompass.sh 8 2 0 " if [[ "$1" =~ ^[0-9]+$ ]]; then # ---- SET INITIAL VALUES ---- length=$1 num=$2 special=$3 # Second and third argument might be empty which means $num and $special # will be empty at this point too. Set the values of $num and $special #to the default values in case they are empty [ "$2" == "" ] && num=4 [ "$3" == "" ] && special=1 else # If user uses arguments then use getopts. while getopts l:n:s:h option do case "${option}" in l) length=${OPTARG};; n) num=${OPTARG};; s) special=${OPTARG};; h) echo "$usage" ;; esac done fi # ---- CHECK ARG VALIDITY ---- # check if the first argument is an integer. If it is not then throw error. #=~ matches REGEXP ^[0-9]+$ which is one or more occurences of the numbers 0-9 if [[ !("$length" =~ ^[0-9]+$ )]]; then echo "Enter numbers only for the password length" echo "$usage" exit fi # check if the second argument is an integer. If it is not then throw error. if [[ !("$num" =~ ^[0-9]+$) ]]; then echo "Enter numbers only for the number of passwords to generate" echo "$usage" exit fi # check if the third argument is an integer. If it is not then throw error. if [[ !("$special" =~ ^[0-1]+$) ]]; then echo "Enter only 0 or 1 for the third argument." echo "$usage" exit fi # ---- GENERATE THE PASSWORDS ---- if [[ $special == "1" ]]; then # if special chars needed: DEFAULT i="0" # echo "first loop for 1" while [ $i -lt $num ] # Keep looping till next password, which satisfies the required criteria, # is successfully generated. May require many more passess for stricter # requirements, usually smaller length passwords. do pass=`tr -dc "A-Za-z0-9_!%" < /dev/urandom | head -c ${length} | xargs` if [ `echo $pass | grep "%" | grep "[0-9]" ` ]; then echo $pass i=$[$i+1] fi done else # if special chars are NOT needed i="0" # echo "second loop for 0" while [ $i -lt $num ] do pass=`tr -dc "A-Za-z0-9" < /dev/urandom | head -c ${length} | xargs` if [ `echo $pass | grep "[0-9]" ` ]; then echo $pass i=$[$i+1] fi done fi
Comments
I noticed that you used getopts to parse options passed.
Unfortunately, getopt doesn't parse options longer than one character.
I wrote about alternative options on my website. If you would like to send you the link to add it as an additional resource, it would be my pleasure.
Regards,
Mokhtar