Yesterday, I was bored and decided to write a random password generator. At first it used numerous temporary files, changed that by using arrays.
This was written on OS X and should work on Linux with minor tweaks (at least change all gshuf to shuf).
Example use:
$ pw -c 3 -l 20 -a b -nsr Vh.9"7`gN;;$kV*/LddE q);S;byf/._Z8;S1|>Kb 3<*FfS&Y&}wD17l[M?y{
Your thoughts and ideas are welcome.
#!/bin/sh
#
#
# Random Password Generator
#
#
#set -x
COUNT=""
ALPHA=""
NUMERICAL=0
SPECIAL=0
STRING_LENGTH=""
RESHUF=0
# delimiters
nu="0-9"
al="a-z"
au="A-Z"
sc="!\"#$%&\'()*+,-./:;<=>?@[\]^_\`{|}~"
urandom_cat() {
# function generates random characters, delimiter gets send from function gen_char_pw
DELIMITER=$1
cat /dev/urandom | env LC_CTYPE=C tr -cd $DELIMITER | head -c 1000
}
usage() {
cat << EOF
This script generates a number of passwords.
usage: $0 -c <number> -l <number> -a <option> -nsr
c and l arguments are REQUIRED!
at least one argument out of a, n and s is required
ARGUMENTS
-h Show this message
-c number Number of passwords to create
-l number Length of password
-a u/l/b Use alphabet (upper-case/lower-case/both)
-n Use numbers
-s Use special characters
-r Reshuffle characters of final password (pretty much useless, but mehh, who cares?)
EOF
}
print_pw() {
# length of phrase gets checked
# in case reshuffle option is ticked, phrase gets reshuffeld and printed out
# else phrase gets printed out. COUNT gets reduced by one
if [[ "$(printf '%s' "$pw" | wc -m)" -eq $STRING_LENGTH ]] ; then
if [[ $RESHUF -eq 1 ]] ; then
echo "$pw" | fold -w 1 | gshuf | tr -d "\\\r\n" ; echo
else
echo "$pw"
fi
COUNT=$(($COUNT-1))
fi
}
gen_char_pw() {
# send delimiter to urandom_cat and fills characters into an array
# then random characters from the array get combined to a password
# trailing newline gets cut off and phrase gets cut to desired length
DELIMITER=$1
i=0
for char in "$((urandom_cat $DELIMITER) | fold -w 1)" ; do
CHARS[$i]=$char
i=$(($i+1))
done
pw="$(gshuf -e "${CHARS[@]}" 2>/dev/null | tr -d "\\\r\n" | head -c $STRING_LENGTH)"
}
gen_pw() {
# lower-case letters
if [[ $ALPHA == l && $NUMERICAL -eq 0 && $SPECIAL -eq 0 ]] ; then
gen_char_pw $al
case "$pw" in
# contained characters get checked
*[a-z]*)
print_pw
;;
esac
# upper_case letters
elif [[ $ALPHA == u && $NUMERICAL -eq 0 && $SPECIAL -eq 0 ]] ; then
gen_char_pw $au
case "$pw" in
*[A-Z]*)
print_pw
;;
esac
# numbers
elif [[ -z $ALPHA && $NUMERICAL -eq 1 && $SPECIAL -eq 0 ]] ; then
gen_char_pw $nu
case "$pw" in
*[0-9]*)
print_pw
;;
esac
# special-characters
elif [[ -z $ALPHA && $NUMERICAL -eq 0 && $SPECIAL -eq 1 ]] ; then
gen_char_pw $sc
case "$pw" in
*[\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~]*)
print_pw
;;
esac
# lower-case and upper-case letters
elif [[ $ALPHA == b && $NUMERICAL -eq 0 && $SPECIAL -eq 0 ]] ; then
gen_char_pw $al$au
case "$pw" in
*[A-Z]*)
case "$pw" in
*[a-z]*)
print_pw
esac
esac
# lower-case letters and numbers
elif [[ $ALPHA == l && $NUMERICAL -eq 1 && $SPECIAL -eq 0 ]] ; then
gen_char_pw $al$nu
case "$pw" in
*[a-z]*)
case "$pw" in
*[0-9]*)
print_pw
;;
esac
esac
# upper-case letters and numbers
elif [[ $ALPHA == u && $NUMERICAL -eq 1 && $SPECIAL -eq 0 ]] ; then
gen_char_pw $au$nu
case "$pw" in
*[A-Z]*)
case "$pw" in
*[0-9]*)
print_pw
;;
esac
esac
# numbers and special-characters
elif [[ -z $ALPHA && $NUMERICAL -eq 1 && $SPECIAL -eq 1 ]] ; then
gen_char_pw $nu$sc
case "$pw" in
*[0-9]*)
case "$pw" in
*[\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~]*)
print_pw
;;
esac
esac
# lower-case letters and special-characters
elif [[ $ALPHA == l && $NUMERICAL -eq 0 && $SPECIAL -eq 1 ]] ; then
gen_char_pw $al$sc
case "$pw" in
*[a-z]*)
case "$pw" in
*[\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~]*)
print_pw
esac
esac
# upper-case letters and special-characters
elif [[ $ALPHA == u && $NUMERICAL -eq 0 && $SPECIAL -eq 1 ]] ; then
gen_char_pw au$sc
case "$pw" in
*[A-Z]*)
case "$pw" in
*[\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~]*)
print_pw
esac
esac
# lower-case letters, numbers and special-characters
elif [[ $ALPHA == l && $NUMERICAL -eq 1 && $SPECIAL -eq 1 ]] ; then
gen_char_pw $al$nu$sc
case "$pw" in
*[0-9]*)
case "$pw" in
*[a-z]*)
case "$pw" in
*[\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~]*)
print_pw
esac
esac
esac
# upper-case letters, numbers and special-characters
elif [[ $ALPHA == u && $NUMERICAL -eq 1 && $SPECIAL -eq 1 ]] ; then
gen_char_pw $au$nu$sc
case "$pw" in
*[0-9]*)
case "$pw" in
*[A-Z]*)
case "$pw" in
*[\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~]*)
print_pw
esac
esac
esac
# lower-case and upper-case letters, numbers
elif [[ $ALPHA == b && $NUMERICAL -eq 1 && $SPECIAL -eq 0 ]] ; then
gen_char_pw $al$au$nu
case "$pw" in
*[0-9]*)
case "$pw" in
*[A-Z]*)
case "$pw" in
*[a-z]*)
print_pw
esac
esac
esac
# lower-case and upper-case letters, special-characters
elif [[ $ALPHA == b && $NUMERICAL -eq 0 && $SPECIAL -eq 1 ]] ; then
gen_char_pw $al$au$sc
case "$pw" in
*[A-Z]*)
case "$pw" in
*[a-z]*)
case "$pw" in
*[\!\@\#\$\%\^\&\*\(\)\_\+\?\>\<\~\`\;\']*)
print_pw
esac
esac
esac
# lower-case and upper-case letters, numbers and special-characters
elif [[ $ALPHA == b && $NUMERICAL -eq 1 && $SPECIAL -eq 1 ]] ; then
gen_char_pw $al$au$nu$sc
case "$pw" in
*[0-9]*)
case "$pw" in
*[A-Z]*)
case "$pw" in
*[a-z]*)
case "$pw" in
*[\!\@\#\$\%\^\&\*\(\)\_\+\?\>\<\~\`\;\']*)
print_pw
esac
esac
esac
esac
fi
}
while getopts c:a:l:nshr opt ; do
case "$opt" in
c) COUNT="$2" ;;
l) STRING_LENGTH="$4" ;;
a) ALPHA="$6" ;;
n) NUMERICAL=1 ;;
s) SPECIAL=1 ;;
r) RESHUF=1 ;;
--) usage
exit 1 ;;
h) usage
exit 1 ;;
*) usage
exit 1 ;;
esac
done
if [[ -z $COUNT ]] || [[ -z $STRING_LENGTH ]] ; then
usage
exit 1
elif [[ -z $ALPHA ]] && [[ $NUMERICAL -eq 0 ]] && [[ $SPECIAL -eq 0 ]] ; then
usage
exit 1
fi
while [ $COUNT -gt 0 ]; do
gen_pw
done
exit 0