From: Steven Baltakatei Sandoval Date: Sat, 23 Jan 2021 03:39:34 +0000 (+0000) Subject: feat(unitproc:bknpass):Add adjusable-length password generator X-Git-Tag: 0.4.0~8 X-Git-Url: https://zdv2.bktei.com/gitweb/BK-2020-03.git/commitdiff_plain/9c8765b4d681d1e705d7cec2d64bbf61ea98efff?ds=sidebyside;hp=-c feat(unitproc:bknpass):Add adjusable-length password generator Takes integer input specifying number of bits of entropy to be encoded in output string. --- 9c8765b4d681d1e705d7cec2d64bbf61ea98efff diff --git a/unitproc/bknpass b/unitproc/bknpass new file mode 100755 index 0000000..4f53da0 --- /dev/null +++ b/unitproc/bknpass @@ -0,0 +1,200 @@ +#!/bin/bash + +# Date: 2020-01-20T16:34Z +# +# Author: Steven Baltakatei Sandoval (baltakatei.com) +# +# License: This bash script, `bknpass`, is licensed under GPLv3 or +# later by Steven Baltakatei Sandoval: +# +# `bknpass`, an alphanumeric password generator +# Copyright (C) 2020 Steven Baltakatei Sandoval (baltakatei.com) +# +# 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 +# the Free Software Foundation, either version 3 of the License, or +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# A copy of the GNU General Public License may be found at +# . +# +# Description: This bash script generates alphanumeric passphrases +# with a char-count determined by a user-provided number of bits of +# entropy. The passphrase is then outputted to stdout with a trailing +# newline. It works as follows: +# +# - Prompt user for an integer. This integer is the number of bits +# of entropy that the generated password should have. +# +# - Check if user-provided string is an integer using `bash` regular +# expression test. +# +# - Calculate the minimum number of alphanumeric characters required +# to encode the specified number of bits of entropy. +# +# - This step uses `bc` to calculate a logarithm float string +# and `awk` to convert the float into an integer, rounding up. +# +# - Use `tr`, `/dev/urandom`, and `head` to generate a random +# alphanumeric string with the length calculated in the previous +# step. +# +# - Use `echo` to display the passphrase in stdout with a trailing +# newline. +# +# Dependencies: bash, echo, bc, awk, tr, head. See end of file +# +# Tested on: +# +# - GNU/Linux Debian 10 + + +#==Initialization== + +let ALPHABET_SIZE="26+26+10" # number of unique chars in [:alnum:], argument fed to `tr -c` in 'Generate passphrase' step) +LOG_BASE=2 # Set logarithm base to 2 + +# Define `echoerr` function which outputs text to stderr + # Note: function copied from https://stackoverflow.com/a/2990533 +function echoerr { + echo "$@" 1>&2; +} + +# Define `rpass` function which generates an alphanumeric passphrase of length $1 (ex: `rpass 22` generates a 22-char string) + # Note: function adapted from https://www.thegeekstuff.com/2010/04/unix-bash-function-examples/ +function rpass { + cat /dev/urandom | LC_ALL=C tr -cd "[:alnum:]" | head -c ${1:-22} +} + + +#==Main Program== + +# Define $ENTROPY_BIT_COUNT1 as argument $1 or prompt user if $1 is not defined. + # note: argument test adapted from https://stackoverflow.com/a/6482403 +if [ -z "$1" ] +then + echo "Entropy bit count argument (\$1) not supplied." + # Get from user the number of bits of entropy. + echoerr -n "Please specify the required strength of the password in bits of entropy (ex: 256):" # prompt via stderr + read ENTROPY_BIT_COUNT1 +else + ENTROPY_BIT_COUNT1="$1" +fi + +# Check if $ENTROPY_BIT_COUNT1 is an non-negative integer + # Note: Regular expression test is adapted from https://stackoverflow.com/a/806923 +RETEST1='^[0-9]+$' +if ! [[ $ENTROPY_BIT_COUNT1 =~ $RETEST1 ]] ; then + echo "error: Not an integer." >&2; exit 1 +fi + +# Calculate minimum count of chars needed to encode $ENTROPY_BIT_COUNT1 with alphabet size of $ALPHABET_SIZE as float + # Solve ln(a^n)/ln(2)=b for n using `bc` where + # a=$ALPHABET_SIZE + # n=$CHAR_COUNT1_FLOAT + # b=$ENTROPY_BIT_COUNT1 + # Note: `bc` logarithm usage adapted from http://phodd.net/gnu-bc/bcfaq.html#bashlog +CHAR_COUNT1_FLOAT=$(echo "$ENTROPY_BIT_COUNT1*l($LOG_BASE)/l($ALPHABET_SIZE)" | bc -l) + # Note: Float will be of form "21.49744370650136860806". This particular float should be rounded to "22" later. + +# Round $CHAR_COUNT1_FLOAT1 up to next highest integer for use as argument in later bash functions. + # Note: awk expression from https://bits.mdminhazulhaque.io/linux/round-number-in-bash-script.html +CHAR_COUNT1=$(echo "$CHAR_COUNT1_FLOAT" | awk '{print ($0-int($0)>0)?int($0)+1:int($0)}') + +# Generate passphrase +PASS1=$(rpass "$CHAR_COUNT1") +echo -e "$PASS1" + + +#==References== +# +# - How to echo a string as stderr instead of stdout. +# https://stackoverflow.com/a/2990533 +# Author: James Roth +# Date: 2010-06-07T14:52Z +# Date Accessed: 2020-01-20 +# +# - How to check if script argument exists or not. +# https://stackoverflow.com/a/6482403 +# Author: phoxix +# Date: 2011-06-26T05:55Z +# Date Accessed: 2020-01-20 +# +# - How to check that a string is an integer using regular expression test. +# https://stackoverflow.com/a/806923 +# Author: Charles Duffy +# Date: 2009-04-30T13:32Z +# Date Accessed: 2020-01-20 +# +# - How to use `bc` to calculate logarithms in Bash +# http://phodd.net/gnu-bc/bcfaq.html#bashlog +# Author: unknown +# Date Accessed: 2020-01-20 +# +# - How to use `awk` to convert and round up a float to an integer. +# https://bits.mdminhazulhaque.io/linux/round-number-in-bash-script.html +# Author: Md. Minhazul Haque +# Date: 2015-01-09 +# Date Accessed: 2020-01-20 +# +# - How to use `/dev/urandom`, `tr`, and `head` to generate a random password in Bash. +# https://www.thegeekstuff.com/2010/04/unix-bash-function-examples/ +# Author: SASIKALA, Ramesh Natarajan +# Date: 2010-04-21 +# Date Accessed: 2020-01-20 +# +# - Dependencies: bash, echo, bc, awk, tr, head. +# +# - GNU bash, version 5.0.3(1)-release (x86_64-pc-linux-gnu) +# Copyright (C) 2019 Free Software Foundation, Inc. +# License GPLv3+: GNU GPL version 3 or later +# This is free software; you are free to change and redistribute it. +# There is NO WARRANTY, to the extent permitted by law. +# +# - echo (GNU coreutils) 8.30 +# Copyright (C) 2018 Free Software Foundation, Inc. +# License GPLv3+: GNU GPL version 3 or later . +# This is free software: you are free to change and redistribute it. +# There is NO WARRANTY, to the extent permitted by law. +# +# Written by Brian Fox and Chet Ramey. +# +# - bc 1.07.1 +# Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc. +# +# - GNU Awk 4.2.1, API: 2.0 (GNU MPFR 4.0.2, GNU MP 6.1.2) +# Copyright (C) 1989, 1991-2018 Free Software Foundation. +# +# 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 +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +# - tr (GNU coreutils) 8.30 +# Copyright (C) 2018 Free Software Foundation, Inc. +# License GPLv3+: GNU GPL version 3 or later . +# This is free software: you are free to change and redistribute it. +# There is NO WARRANTY, to the extent permitted by law. +# +# Written by Jim Meyering. +# +# - head (GNU coreutils) 8.30 +# Copyright (C) 2018 Free Software Foundation, Inc. +# License GPLv3+: GNU GPL version 3 or later . +# This is free software: you are free to change and redistribute it. +# There is NO WARRANTY, to the extent permitted by law. +# +# Written by David MacKenzie and Jim Meyering.