# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -euo pipefail
USAGE="${BOLD}${UNDERLINE}${RED}Usage${RESET}
${BOLD}${GREEN}$THIS new password [option...]${RESET}
${BOLD}${UNDERLINE}${RED}Description${RESET}
Generates a new password hash in libxcrypt format with secure defaults.
For more advanced usage run the ${BOLD}${MAGENTA}\`mkpasswd\`${RESET} utility directly.
${BOLD}${UNDERLINE}${RED}Options${RESET}
${BOLD}${MAGENTA}-h, --help${RESET} Show this message (^_^)
${BOLD}${MAGENTA}-o, --out${RESET} Private key file name to write to (the public key is named identically but ends with ${BOLD}${CYAN}.pub${RESET})
${BOLD}${MAGENTA}-j, --json${RESET} Output in JSON format
${BOLD}${MAGENTA}-i, --stdin${RESET} Read the password to hash from stdin ${BOLD}$CYAN(single line only)${RESET}
${BOLD}${MAGENTA}-t, --type${RESET} The hash algorithm to use: ${BOLD}${MAGENTA}yescrypt, scrypt, bcrypt ${CYAN}(default: yescrypt)${RESET}
${BOLD}${MAGENTA}-r, --rounds${RESET} The number of key derivation function rounds to apply ${BOLD}${MAGENTA}(format: ^[0-9]+\$) ${CYAN}(defaults: yescrypt=11, scrypt=10, bcrypt=14)${RESET}
${BOLD}${MAGENTA}-s, --salt${RESET} Specify the hash's salt directly ${BOLD}${RED}(not recommended)${RESET} ${BOLD}${CYAN}(default: libxcrypt secure default)${RESET}"
# ==== Argument Values ====
TYPE='yescrypt'
ROUNDS=''
SALTED=false
OUT=''
JSON=false
STDIN=false
EXTRA=''
# ==== Argument Values ====
# parse all args
while [[ $# -gt 0 ]]; do
ARG="$1"
case "$ARG" in
-h|--help)
throw-usage 0
;;
-o|--out)
shift
OUT="$1"; shift
;;
-j|--json)
shift
JSON=true
;;
-i|--stdin)
shift
STDIN=true
;;
-t|--type)
shift
TYPE="$1"; shift
;;
-r|--rounds)
shift
ROUNDS="$1"; shift
;;
-s|--salt)
shift
if [[ "$SALTED" == false ]]; then
SALTED=true
EXTRA="$EXTRA --salt=\'$1\'"
fi
shift
;;
-*)
throw-badflag 1 "$ARG"
;;
*)
throw-badarg 1 "$ARG"
;;
esac
done; unset -v ARG
# NOTE: Available password hashing methods for /etc/passwd & /etc/shadow
# NOTE: Read the manual pages via `man 3 crypt` and `man 5 crypt` (if available)
# NOTE: Available online via https://man.archlinux.org/man/crypt.5
# WARNING: Due to modern developments in cryptography most of these methods
# WARNING: are no longer recommended however some distrobutions still use them.
# WARNING: Cerulean intentionally restricts access to only secure algorithms.
# $ mkpasswd -m help
## Available methods:
## yescrypt Yescrypt
## gost-yescrypt GOST Yescrypt
## scrypt scrypt
## bcrypt bcrypt
## bcrypt-a bcrypt (obsolete $2a$ version)
## sha512crypt SHA-512
## sha256crypt SHA-256
## sunmd5 SunMD5
## md5crypt MD5
## bsdicrypt BSDI extended DES-based crypt(3)
## descrypt standard 56 bit DES-based crypt(3)
## nt NT-Hash
function perr-unsupportedhash {
local ALGO="$1"
echo -e "${BOLD}${CYAN}$THIS${RED} does not support the ${MAGENTA}$ALGO${RED} hashing algorithm${RESET}" >&2