Skip to content

Instantly share code, notes, and snippets.

@steverichey steverichey/pw
Created Oct 25, 2019

Embed
What would you like to do?
Simple password generator, version 2
#!/usr/bin/env sh
set -eur
generate()
{
allowed_characters="${1}"
number_of_characters="${2}"
cat /dev/random | env LC_CTYPE=C tr -cd "${allowed_characters}" | head -c "${number_of_characters}"
}
get_line()
{
line_number="${1}"
file_name="${2}"
awk '/'${line_number}'/{ print NR; exit }' "${file_name}"
}
get_word()
{
text_line="${1}"
file_name="${2}"
awk 'NR=='${text_line}'' ${file_name}
}
echored()
{
(>&2 echo "\033[1;31m${1}\033[0m")
}
echoyellow()
{
echo "\033[1;33m${1}\033[0m"
}
echogreen()
{
echo "\033[1;32m${1}\033[0m"
}
usage ()
{
echogreen "Usage: pw [options] length"
echo "Generates a random password with the given limitations, and copies to the clipboard"
echo "\t-n\tNumeric character limitation"
echo "\t-a\tAlphabetic character limitation"
echo "\t-l\tLowercase character limitation"
echo "\t-d\tDiceware passphrase (exclusive to other options)"
echo "\t-p\tPrint password or passphrase instead of copying to clipboard"
echo ""
exit 1
}
numeric_characters=0
alpha_characters=0
lowercase_characters=0
diceware=0
print_output=0
length=""
numeric_regex="^[0-9]+$"
# parse arguments
while [ $# -gt 0 ]
do
case "${1}" in
"-h"|"--help")
usage
shift
;;
"-n"|"--numeric")
numeric_characters=1
shift
;;
"-a"|"--alpha")
alpha_characters=1
shift
;;
"-l"|"--lowercase")
lowercase_characters=1
shift
;;
"-d"|"--diceware"|"-w")
diceware=1
shift
;;
"-p"|"--print")
print_output=1
shift
;;
*) # all other parameters
if [[ "${length}" == "" && "${1}" =~ ${numeric_regex} ]]; then
length="${1}"
else
echored "Invalid or unexpected argument: ${1}"
exit 1
fi
shift
;;
esac
done
if [ "${length}" == "" ]; then
echored "Length is required; must be a numeric value"
exit 1
fi
numeric_regex="^[0-9]+$"
if ! [[ "${length}" =~ ${numeric_regex} ]] ; then
echored "Given value was not a number"
exit 1
fi
if [ "${diceware}" == "1" ]; then
set +u
if [ -z "${DICEWARE_FILENAME}" ]; then
echored "Please set DICEWARE_FILENAME to the location of your diceware text file."
exit 1
fi
phrase=""
for i in `seq 1 ${length}`
do
dice_number=`generate '1-6' 5`
word_line=`get_line "${dice_number}" "${DICEWARE_FILENAME}"`
whole_word=`get_word "${word_line}" "${DICEWARE_FILENAME}"`
split_word=(${whole_word// / })
phrase="${phrase} ${split_word[1]}"
done
set -u
if [ "${print_output}" == "1" ]; then
echo ${phrase}
else
echo ${phrase} | tr -d '\n' | pbcopy
echogreen "Copied to clipboard"
fi
else
allowed_characters=""
if [ "${numeric_characters}" == "1" ]; then
allowed_characters="${allowed_characters}0-9"
fi
if [ "${alpha_characters}" == "1" ]; then
if [ "${lowercase_characters}" == "1" ]; then
allowed_characters="${allowed_characters}a-z"
else
allowed_characters="${allowed_characters}A-Za-z"
fi
fi
if [ "${allowed_characters}" == "" ]; then
allowed_characters='a-zA-Z0-9`~!@#$%^&*()_+-={}[]|;<,>.?/'
fi
if [ "${print_output}" == "1" ]; then
generate "${allowed_characters}" "${length}" | xargs echo
else
generate "${allowed_characters}" "${length}" | pbcopy
echogreen "Copied to clipboard"
fi
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.