#!/usr/bin/env sh # Filename: makepass.sh # Purpose: Creating random passwords. # Authors: Dennis Eriksen # Bug-Reports: Email # License: This file is licensed under the BSD 3-Clause license. ################################################################################ # This file takes randomness from /dev/urandom and turns it into random # passwords. # # This particualr script is meant to be fully POSIX compatible. ################################################################################ # Copyright (c) 2018-2023 Dennis Eriksen • d@ennis.no # makepass-function makepass() { MAKEPASS_WORDLIST=${MAKEPASS_WORDLIST:-/usr/share/dict/words} # We only take one argument [ "$#" -gt 1 ] && printf '%s\n' 'only one argument' && return 1 # if $1 is not empty and is not a number if [ ! -z "$1" ] && ! printf '%d' "$1" >/dev/null 2>&1; then printf '%s\n' 'not a number' && return 1; fi if [ ! -z "$1" ] && [ ! ${1:-0} -gt 0 ]; then printf '%s\n' 'not a number above 0'; return 1; fi # Go! len=$1 printf '%s\n' 'Normal passwords:' i=0 while [ $i -lt 10 ]; do _random "${len:-}" '_A-Z-a-z-0-9' true i=$((i + 1)) done | column printf '\n' printf '%s\n' 'Passwords with special characters:' i=0 while [ $i -lt 6 ]; do _random "${len:-}" '!#$%&/()=?+-_,.;:<>[]{}|\@*^A-Z-a-z-0-9' true i=$((i + 1)) done | column if [ -r "${MAKEPASS_WORDLIST}" ]; then printf '\n' printf '%s\n' 'Passphrases:' lines=$(wc -l < ${MAKEPASS_WORDLIST}) i=0 while [ $i -lt 5 ]; do # shuf is the best solution here, but it is very much not portable. #words=$(shuf -n 8 "${MAKEPASS_WORDLIST}" | tr '\n' '-' | tr -dc '_A-Z-a-z-0-9') words="" j=0 while [ $j -lt 8 ]; do words="${words}-$(sed -n $(($(_RANDOM) % $lines + 1))p "${MAKEPASS_WORDLIST}" | tr -dc '_A-Z-a-z-0-9')" j=$((j + 1)) done printf '%s\n' "${words#-}" i=$((i + 1)) done fi unset len i lines j words return 0 } # get random number _RANDOM() { N=0 while [ ! "$N" = "${N#0}" ]; do N=$(head -n 100 /dev/urandom | tr -cd "[:digit:]" | tail -c 8) done printf '%s\n' "$N" && return 0 } # Function to create random stuff _random() ( # sh does not like leading zeroes when doing math with numbers. Let's reset until we have a number that doesn't start with 0. # Default is a number between 8 and 44 len=${1:-$(($(_RANDOM) % (44 - 8 + 1) + 8))} # Default to [:alnum:] if no chars are specified chars=${2:-'[:alnum:]'} # First-Last-Alpha - if you want the first and the last letter to be from [:alpha:] fla=${3:-'false'} if [ "$fla" = "true" ]; then if [ $len -le 2 ]; then string="$(head -n 10 /dev/urandom | tr -cd '[:alpha:]' | tail -c $len)" else string="$(head -n 10 /dev/urandom | tr -cd '[:alpha:]' | tail -c 1)" string="${string}$(head -n 100 /dev/urandom | tr -cd "$chars" | tail -c $((len-2)))" string="${string}$(head -n 10 /dev/urandom | tr -cd '[:alpha:]' | tail -c 1)" fi else string="$(head -n 100 /dev/urandom | tr -cd "$chars" | tail -c $len)" fi printf '%s\n' "$string" unset len chars fla string return 0 ) makepass "${@:-}" ## END OF FILE #################################################################