diff options
-rwxr-xr-x | makepass.zsh | 310 |
1 files changed, 155 insertions, 155 deletions
diff --git a/makepass.zsh b/makepass.zsh index 558585b..e76edc9 100755 --- a/makepass.zsh +++ b/makepass.zsh @@ -48,6 +48,161 @@ typeset -gi COL_NUM # Number of columns to print # Functions # +# main-function. This is where the magic happens +function main() { + setopt localoptions + + # Getopts + while getopts 'hl:n:p' opt; do + case $opt in + h) + _makepass_help && return 0;; + l) + [[ $OPTARG = <0-> && $OPTARG -le $MAX ]] || die "-l takes a number between 0 and $MAX" + LENGTH=$OPTARG;; + n) + [[ $OPTARG = <1-> && $OPTARG -le $MAX ]] || die "-n takes a number between 1 and $MAX" + NUMBER=$OPTARG;; + p) + PRINTLEN=1;; + *) + die "Unknown argument";; + esac + done + shift $((OPTIND - 1)) + + + # + # Some error-checking + # + + # We only take one argument in addition to the optargs + (( ARGC > 1 )) && die "only one argument" + + # if there is an argument, set it to $LENGTH + [[ -n $1 ]] && LENGTH=$1 + + # Check $LENGTH and $NUMBER + # Both are integers so no need to check if they are numbers + # If they were somehow assigned to, say "xx", they would be 0 + (( 0 <= LENGTH && LENGTH <= MAX )) || die "length must be a number between 0 and $MAX" + (( 1 <= NUMBER && NUMBER <= MAX )) || die "number-argument must be between 1 and $MAX" + + + # + # Some other work + # + + # Seed $RANDOM with a random 32bit integer from /dev/random + local r4 # will be filled with 4 random bytes from /dev/random + IFS= read -rk4 -u0 r4 < /dev/random || return + local b1=$r4[1] b2=$r4[2] b3=$r4[3] b4=$r4[4] + RANDOM=$(( #b1 << 24 | #b2 << 16 | #b3 << 8 | #b4 )) + + # We zero-pad printlength, so we need three extra chars if LENGTH < 100 (four + # if LENGTH >= 100). Two for printlength, one for the space. + (( PRINTLEN )) && { ((LENGTH < 100)) && PRINTLEN=3 || PRINTLEN=4 } + + # Calculate width of columns and number of columns to use + # add two for spacing between columns + COL_WIDTH=$(( ( LENGTH ? LENGTH : RANGE_MAX ) + PRINTLEN + 2 )) + # $COLUMNS is a builtin variable for width of terminal + COL_NUM=$(( COLUMNS / COL_WIDTH )) + # Just in case COL_NUM=0 because of a small terminal or something + (( COL_NUM )) || COL_NUM=1 + + + # + # Print! + # + + print_columns "Passwords with special characters" $NUMBER $NORMAL + + print; : $RANDOM # Just to make sure we get a fresh number + + print_columns "Passwords with special characters" $((NUMBER/3*2+1)) $SPECIAL + + # Passphrases - but only if a wordlist is available + if [[ -r $WORDLIST ]] && ((NUMBER / 2 > 0)); then + print; : $RANDOM + print "Passphrases:" + # Read wordlist into array + WORDS=(${(f)"$(<$WORDLIST)"}) + # Run passphrase-function to output passphrases + repeat $((NUMBER / 2)) passphrase + fi +} + +# Function to print passwords in neat columns +function print_columns() { + local title=$1 + local num=$2 + local chars=$3 + local -i i=0 + + local strings=($(repeat $num { randstring $chars; : $RANDOM })) + + print -- "$title" + + for s in $strings; do + let i++ + (( PRINTLEN )) && s="$#s $s" + printf "%-${COL_WIDTH}s" $s; + ((i % COL_NUM == 0 || (i == num && i % COL_NUM > 0))) && print + done +} + +# Function to create random strings +function randstring() { + local chars=${1:-$NORMAL} + local string + local -i len=$(( LENGTH \ + ? LENGTH \ + : RANDOM % (RANGE_MAX - RANGE_MIN + 1) + RANGE_MIN )) + + repeat $len string+=$chars[$((RANDOM % $#chars + 1))] + + if ((len >= 2)); then + # add new character to start of line and remove 2 from old string + string=$ALPHA[$((RANDOM % $#ALPHA + 1))]$string[2,-2] + # add new character to end of string + string+=$ALPHA[$((RANDOM % $#ALPHA + 1))] + fi + + print -- $string; return +} + +# Create random passphrase +function passphrase() { + setopt localoptions rematch_pcre + + local prestring string + + # Put together $len random words, separated by '-' + repeat $PASS_WORDS prestring+=$WORDS[$((RANDOM % $#WORDS + 1))]'-' + prestring=$prestring[1,-2] # remove trailing dash + + # This while-loop removes any characters NOT in '[^0-9a-zA-Z_-]' + while [[ -n $prestring ]]; do + if [[ $prestring =~ '[^0-9a-zA-Z_-]' ]]; then + string+=${prestring[1,MBEGIN-1]} + prestring=${prestring[MEND+1,-1]} + else + break + fi + done + string+=$prestring # append the rest of $prestring + + printf '%s\n' $string; return +} + +# Function to die +function die() { + print -u2 -- "$@" + print -u2 -- "Maybe try running \`$ZSH_SCRIPT -h\` for help" + exit 1 +} + # Help-function function _makepass_help() { print -- $'NAME @@ -137,161 +292,6 @@ AUTHOR return 0 } -# Create random passphrase -function passphrase() { - setopt localoptions rematch_pcre - - local prestring string - - # Put together $len random words, separated by '-' - repeat $PASS_WORDS prestring+=$WORDS[$((RANDOM % $#WORDS + 1))]'-' - prestring=$prestring[1,-2] # remove trailing dash - - # This while-loop removes any characters NOT in '[^0-9a-zA-Z_-]' - while [[ -n $prestring ]]; do - if [[ $prestring =~ '[^0-9a-zA-Z_-]' ]]; then - string+=${prestring[1,MBEGIN-1]} - prestring=${prestring[MEND+1,-1]} - else - break - fi - done - string+=$prestring # append the rest of $prestring - - printf '%s\n' $string; return -} - -# Function to create random strings -function randstring() { - local chars=${1:-$NORMAL} - local string - local -i len=$(( LENGTH \ - ? LENGTH \ - : RANDOM % (RANGE_MAX - RANGE_MIN + 1) + RANGE_MIN )) - - repeat $len string+=$chars[$((RANDOM % $#chars + 1))] - - if ((len >= 2)); then - # add new character to start of line and remove 2 from old string - string=$ALPHA[$((RANDOM % $#ALPHA + 1))]$string[2,-2] - # add new character to end of string - string+=$ALPHA[$((RANDOM % $#ALPHA + 1))] - fi - - print -- $string; return -} - -# Function to print passwords in neat columns -function print_columns() { - local title=$1 - local num=$2 - local chars=$3 - local -i i=0 - - local strings=($(repeat $num { randstring $chars; : $RANDOM })) - - print -- "$title" - - for s in $strings; do - let i++ - (( PRINTLEN )) && s="$#s $s" - printf "%-${COL_WIDTH}s" $s; - ((i % COL_NUM == 0 || (i == num && i % COL_NUM > 0))) && print - done -} - -# Function to die -function die() { - print -u2 -- "$@" - print -u2 -- "Maybe try running \`$ZSH_SCRIPT -h\` for help" - exit 1 -} - -# main-function. This is where the magic happens -function main() { - setopt localoptions - - # Getopts - while getopts 'hl:n:p' opt; do - case $opt in - h) - _makepass_help && return 0;; - l) - [[ $OPTARG = <0-> && $OPTARG -le $MAX ]] || die "-l takes a number between 0 and $MAX" - LENGTH=$OPTARG;; - n) - [[ $OPTARG = <1-> && $OPTARG -le $MAX ]] || die "-n takes a number between 1 and $MAX" - NUMBER=$OPTARG;; - p) - PRINTLEN=1;; - *) - die "Unknown argument";; - esac - done - shift $((OPTIND - 1)) - - - # - # Some error-checking - # - - # We only take one argument in addition to the optargs - (( ARGC > 1 )) && die "only one argument" - - # if there is an argument, set it to $LENGTH - [[ -n $1 ]] && LENGTH=$1 - - # Check $LENGTH and $NUMBER - # Both are integers so no need to check if they are numbers - # If they were somehow assigned to, say "xx", they would be 0 - (( 0 <= LENGTH && LENGTH <= MAX )) || die "length must be a number between 0 and $MAX" - (( 1 <= NUMBER && NUMBER <= MAX )) || die "number-argument must be between 1 and $MAX" - - - # - # Some other work - # - - # Seed $RANDOM with a random 32bit integer from /dev/random - local r4 # will be filled with 4 random bytes from /dev/random - IFS= read -rk4 -u0 r4 < /dev/random || return - local b1=$r4[1] b2=$r4[2] b3=$r4[3] b4=$r4[4] - RANDOM=$(( #b1 << 24 | #b2 << 16 | #b3 << 8 | #b4 )) - - # We zero-pad printlength, so we need three extra chars if LENGTH < 100 (four - # if LENGTH >= 100). Two for printlength, one for the space. - (( PRINTLEN )) && { ((LENGTH < 100)) && PRINTLEN=3 || PRINTLEN=4 } - - # Calculate width of columns and number of columns to use - # add two for spacing between columns - COL_WIDTH=$(( ( LENGTH ? LENGTH : RANGE_MAX ) + PRINTLEN + 2 )) - # $COLUMNS is a builtin variable for width of terminal - COL_NUM=$(( COLUMNS / COL_WIDTH )) - # Just in case COL_NUM=0 because of a small terminal or something - (( COL_NUM )) || COL_NUM=1 - - - # - # Print! - # - - print_columns "Passwords with special characters" $NUMBER $NORMAL - - print; : $RANDOM # Just to make sure we get a fresh number - - print_columns "Passwords with special characters" $((NUMBER/3*2+1)) $SPECIAL - - # Passphrases - but only if a wordlist is available - if [[ -r $WORDLIST ]] && ((NUMBER / 2 > 0)); then - print; : $RANDOM - print "Passphrases:" - # Read wordlist into array - WORDS=(${(f)"$(<$WORDLIST)"}) - # Run passphrase-function to output passphrases - repeat $((NUMBER / 2)) passphrase - fi -} - # Run main function! GOGOGO! main "${@:-}" |