Skip to content

Instantly share code, notes, and snippets.

@steverichey
Created October 25, 2019 21:54
Show Gist options
  • Save steverichey/6fb2f5e3684ca527497cd88bc8e720e7 to your computer and use it in GitHub Desktop.
Save steverichey/6fb2f5e3684ca527497cd88bc8e720e7 to your computer and use it in GitHub Desktop.
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