dotfiles/bin/random_password.sh

56 lines
1.5 KiB
Bash
Raw Normal View History

2023-12-23 20:13:47 -07:00
#!/usr/bin/env bash
print_help() {
cat <<HELP
Generate a random password from /dev/urandom, with characters from /[A-z0-9;-]/
Usage: $(basename "$0") <output-length>
Examples:
$(basename "$0") 20 | wl-copy
$(basename "$0") 400 > key_file
Special characters: /[;-]/
Length must be at least $MIN_PASSWORD_LENGTH. Passwords are generated until one of each a
lowercase, uppercase, digit, and special character are in the password.
Both special characters are required for passwords >=$LONG_PASSWORD_LENGTH characters long.
Really long passwords have at least 2 of each special character.
HELP
}
shopt -s lastpipe
declare -ri LONG_PASSWORD_LENGTH=15 MIN_PASSWORD_LENGTH=6
declare -gri LENGTH="$1"
declare password=""
generate_password() {
dd if=/dev/urandom bs=3 count="$(( 10 * LENGTH ))" 2>/dev/null \
| base64 -w0 \
| tr '/' '-' \
| tr '+' ';' \
| cut -c "1-$LENGTH" \
| read -r password
}
contains_characterset() {
local p="$password"
if [[ $LENGTH -ge $(( 2*LONG_PASSWORD_LENGTH )) ]]; then
[[ $p =~ [A-Z] && $p =~ [a-z] && $p =~ [0-9] && $p =~ \;.+\; && $p =~ -.+- ]]
elif [[ $LENGTH -ge $LONG_PASSWORD_LENGTH ]]; then
[[ $p =~ [A-Z] && $p =~ [a-z] && $p =~ [0-9] && $p =~ \; && $p =~ - ]]
else
[[ $p =~ [A-Z] && $p =~ [a-z] && $p =~ [0-9] ]] && [[ $p =~ \; || $p =~ - ]]
fi
}
if [[ "$1" =~ ^[0-9]+$ && $1 -ge $MIN_PASSWORD_LENGTH ]]; then
while ! contains_characterset; do
generate_password "$1"
done
echo "$password"
else
print_help
exit 1
fi