diff --git a/profile/_assets/bin/mkpw b/profile/_assets/bin/mkpw index eb0b6ba6882f25c1627d74929b19c0efc041da56..3d6de092fa2a9dfaffa5b4f8c743de2923294d54 100755 --- a/profile/_assets/bin/mkpw +++ b/profile/_assets/bin/mkpw @@ -1,23 +1,20 @@ -#!/bin/bash +#!/usr/bin/env bash -# File: mkpw.sh +# File: mkpw # Author: Sven Mäder <maeder@phys.ethz.ch>, ETH Zurich, ISG D-PHYS -# Date: 2019-03-01 +# Date: 2024-08-29 # Github: https://github.com/rda0/mkpw/blob/master/mkpw.sh # # Description: Generates random secure passwords suitable for linux logins, -# prints out the creatext password and the corresponding -# `sha-512` hash. The hash includes a random salt and 10000 -# rounds. All randomness is generated using `/dev/urandom`. -# Example: tty=/dev/ttyS will match all logins via a serial -# console like /dev/ttyS0, /dev/ttyS1, etc. +# prints out the creatext password and the corresponding hash. +# Alternatively hashes input password. # # Requirement: `mkpasswd`, provided by the package whois, on debian based # distributions run the following command to install it: # # apt install whois # -# Copyright 2017 Sven Mäder +# Copyright 2024 Sven Mäder # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -46,33 +43,30 @@ charset_q='\\\-_~!@#$%^&*()+={}[]|;:<>,.?/a-zA-Z0-9' passwd_charset=${charset_g} # character set to use for salts (allowed charset = ./a-zA-Z0-9 ) salt_charset='./a-zA-Z0-9' -# hashing algorithm used (use: sha-256 | sha-512) -hash_algorithm='sha-512' -# maximum password length -passwd_max_des=8 # minimum password length not showing insecure warning passwd_min=12 -# salt length (sha: min=8, max=16, md5: 8) -salt_len_sha=16 -salt_len_md5=8 -salt_len_des=2 -# default salt len -salt_len=${salt_len_sha} -# number of rounds the password is hashed (min=1'000, max=999'999'999) -rounds=10000 +# default password length +passwd_len=32 +# default rounds (-1 == use defaults) +rounds=-1 +# default salt_len (-1 == use defaults) +salt_len=-1 # possible hashing algorithms -methods='sha-512 sha-256 md5 des' +methods='yescrypt gost-yescrypt scrypt bcrypt bcrypt-a sha512crypt sha256crypt sunmd5 md5crypt bsdicrypt descrypt nt' # default method -method='sha-512' +method='yescrypt' +# hash input (provide existing password to hash) +hash_input=0 +hash_input_stdin=0 ## loop variables - +# loop counter counter=0 +# default number of passwords to generate amount=1 -passwd_len=32 print_usage() { - echo -e "Usage: ${0} [option] [length [amount]]" + echo -e "Usage: ${0} [options] [length [amount]]" echo -e "\n Generates strong passwords suitable for linux logins." echo -e "\nOutput: <cleartext-password> <hashed-password>" echo -e "\nOptions:\n" @@ -97,12 +91,24 @@ print_usage() { echo " -m, --method TYPE" echo " Compute the password using the TYPE method." echo " Possible values for TYPE:" - echo " sha-512 SHA-512 (default)" - echo " sha-256 SHA-256" - echo " md5 MD5" - echo " des standard 56 bit DES-based crypt(3)" + echo " yescrypt Yescrypt (default)" + echo " gost-yescrypt GOST Yescrypt" + echo " scrypt scrypt" + echo " bcrypt bcrypt" + echo ' bcrypt-a bcrypt (obsolete $2a$ version)' + echo " sha512crypt SHA-512" + echo " sha256crypt SHA-256" + echo " sunmd5 SunMD5" + echo " md5crypt MD5" + echo " bsdicrypt BSDI extended DES-based crypt(3)" + echo " descrypt standard 56 bit DES-based crypt(3)" + echo " nt NT-Hash" echo " -r, --rounds ROUNDS" - echo " Compute the password using ROUNDS number of rounds (default=10000)." + echo " Compute the password using ROUNDS number of rounds (otherwise use default)." + echo " -i, --hash-input" + echo " Hash input password." + echo " -s, --stdin" + echo " Read input password from stdin (only with -i)." } check_opt() { @@ -140,7 +146,7 @@ if [ "$(which mkpasswd)" != "/usr/bin/mkpasswd" ]; then exit 1 fi -if [ "$#" -lt 0 ] || [ "$#" -gt 7 ]; then +if [ "$#" -lt 0 ] || [ "$#" -gt 9 ]; then print_usage exit 1 fi @@ -152,10 +158,10 @@ while [[ $# -gt 0 ]] do key="$1" -case $key in +case ${key} in -h|--help) print_usage - exit 1 + exit 0 ;; -g|--graph) check_opt @@ -206,23 +212,29 @@ case $key in ;; -r|--rounds) valid_rounds='[0-9]' - if [[ ${2} =~ ${valid_rounds} ]] && [ ${2} -ge 1000 ] && [ ${2} -le 999999999 ]; then + if [[ "${2}" =~ ${valid_rounds} ]] && [ "${2}" -ge 0 ] && [ "${2}" -le 999999999 ]; then rounds=${2} shift else echo -e "Error: Invalid value for rounds\n" >&2 - echo -e "Provide a numeric value between 1000 and 999999999\n" >&2 + echo -e "Provide a numeric value between 0 and 999999999\n" >&2 print_usage exit 1 fi ;; + -i|--hash-input) + hash_input=1 + ;; + -s|--stdin) + hash_input_stdin=1 + ;; *) if [ ${num} -ge 2 ]; then echo -e "Error: Too many arguments\n" >&2 print_usage exit 1 fi - check_num ${1} + check_num "${1}" if [ ${num} -eq 0 ]; then passwd_len="${1}" fi @@ -235,37 +247,105 @@ esac shift # past argument or value done +# defaults for algorithms case ${method} in - sha-512) - salt_len=${salt_len_sha} + # for possible salt lengths see man crypt(5) + yescrypt) + # debian default rounds: 5 + if [ "${rounds}" == "-1" ]; then + rounds=7 + fi ;; - sha-256) - salt_len=${salt_len_sha} + sha512crypt) + salt_len=16 + if [ "${rounds}" == "-1" ]; then + # debian default rounds: 5000 + rounds=500000 + fi + ;; + sha256crypt) + salt_len=16 + if [ "${rounds}" == "-1" ]; then + rounds=500000 + fi ;; - md5) - salt_len=${salt_len_md5} + md5crypt) + salt_len=8 + rounds=-1 ;; - des) - salt_len=${salt_len_des} - passwd_max=${passwd_max_des} + descrypt) + salt_len=2 + passwd_max=8 + rounds=-1 ;; esac +# default uses no --rounds param and defaults of mkpasswd +rounds_param="" + +if [ "${rounds}" != "-1" ]; then + rounds_param="--rounds=${rounds}" +fi + +# default uses no --salt param and defaults of mkpasswd +salt_param="" + if [ "${passwd_len}" -lt "${passwd_min}" ]; then - print_passwd_insecure + print_passwd_insecure fi + if [ ! -z "${passwd_max}" ] && [ "${passwd_len}" -gt "${passwd_max}" ]; then - print_passwd_too_long - exit 1 + print_passwd_too_long + exit 1 fi -hash_algorithm=${method} +while [ "${counter}" -lt "${amount}" ]; do + if [ "${salt_len}" != "-1" ]; then + salt=$(head -c"${salt_len}" < <(LC_CTYPE=C tr -dc "${salt_charset}" < /dev/urandom)) + salt_param="--salt=${salt}" + fi + + if [ "${hash_input}" -eq 0 ]; then + # generate random password + passwd=$(head -c"${passwd_len}" < <(LC_CTYPE=C tr -dc "${passwd_charset}" < /dev/urandom)) + echo -n "${passwd}" + echo -n ' ' + if [ "${rounds_param}" != "" ] && [ "${salt_param}" != "" ]; then + echo -n "${passwd}" | /usr/bin/mkpasswd -s -m "${method}" "${rounds_param}" "${salt_param}" + elif [ "${rounds_param}" != "" ]; then + echo -n "${passwd}" | /usr/bin/mkpasswd -s -m "${method}" "${rounds_param}" + elif [ "${salt_param}" != "" ]; then + echo -n "${passwd}" | /usr/bin/mkpasswd -s -m "${method}" "${salt_param}" + else + echo -n "${passwd}" | /usr/bin/mkpasswd -s -m "${method}" + fi + else + amount=1 + if [ "${hash_input_stdin}" -eq 1 ]; then + # hash password from stdin + passwd=$(cat) + if [ "${rounds_param}" != "" ] && [ "${salt_param}" != "" ]; then + echo -n "${passwd}" | /usr/bin/mkpasswd -s -m "${method}" "${rounds_param}" "${salt_param}" + elif [ "${rounds_param}" != "" ]; then + echo -n "${passwd}" | /usr/bin/mkpasswd -s -m "${method}" "${rounds_param}" + elif [ "${salt_param}" != "" ]; then + echo -n "${passwd}" | /usr/bin/mkpasswd -s -m "${method}" "${salt_param}" + else + echo -n "${passwd}" | /usr/bin/mkpasswd -s -m "${method}" + fi + else + # hash password from user input + if [ "${rounds_param}" != "" ] && [ "${salt_param}" != "" ]; then + /usr/bin/mkpasswd -m "${method}" "${rounds_param}" "${salt_param}" + elif [ "${rounds_param}" != "" ]; then + /usr/bin/mkpasswd -m "${method}" "${rounds_param}" + elif [ "${salt_param}" != "" ]; then + /usr/bin/mkpasswd -m "${method}" "${salt_param}" + else + /usr/bin/mkpasswd -m "${method}" + fi + fi + fi -while [ $counter -lt $amount ]; do - passwd=$(head -c"${passwd_len}" < <(LC_CTYPE=C tr -dc "${passwd_charset}" < /dev/urandom)) - salt=$(head -c"${salt_len}" < <(LC_CTYPE=C tr -dc "${salt_charset}" < /dev/urandom)) - echo -n "${passwd}" - echo -n ' ' - echo -n "${passwd}" | /usr/bin/mkpasswd -s -m "${hash_algorithm}" -R "${rounds}" -S "${salt}" - let counter+=1 + ((counter+=1)) done