style(user/bknpass):Simplify boilerplate
[BK-2020-03.git] / user / bknpass
CommitLineData
2feb5df8 1#!/bin/bash
203add48
SBS
2# Desc: Generate alphanumeric passphrase with specified bits of entropy.
3# Usage: bknpass [int]
4# Example: bknpass 128
5# Depends: bash, echo, bc, awk, tr, head, Debian 10
6# Version: 0.1.0
7# Note: This bash script generates alphanumeric passphrases
8# with a char-count determined by a user-provided number of bits of
9# entropy. The passphrase is then outputted to stdout with a trailing
10# newline. It works as follows:
2feb5df8 11#
203add48
SBS
12# - Prompt user for an integer. This integer is the number of bits
13# of entropy that the generated password should have.
2feb5df8 14#
203add48
SBS
15# - Check if user-provided string is an integer using `bash` regular
16# expression test.
2feb5df8 17#
203add48
SBS
18# - Calculate the minimum number of bech32 base32 characters
19# required to encode the specified number of bits of entropy.
2feb5df8 20#
203add48
SBS
21# - This step uses `bc` to calculate a logarithm float string
22# and `awk` to convert the float into an integer, rounding up.
2feb5df8 23#
203add48
SBS
24# - Use `tr`, `/dev/urandom`, and `head` to generate a random
25# alphanumeric string with the length calculated in the previous
26# step.
2feb5df8 27#
203add48
SBS
28# - Use `echo` to display the passphrase in stdout with a trailing
29# newline.
2feb5df8
SBS
30
31
32#==Initialization==
33
34let ALPHABET_SIZE="32" # number of unique chars in bech32 base32 charset
35LOG_BASE=2 # Set logarithm base to 2
36
37# Define `echoerr` function which outputs text to stderr
38 # Note: function copied from https://stackoverflow.com/a/2990533
39function echoerr {
40 echo "$@" 1>&2;
41}
42
43# Define `rpass` function which generates a base32 passphrase of length $1 (ex: `rpass 20` generates a 20-char string)
44# Note: function adapted from https://www.thegeekstuff.com/2010/04/unix-bash-function-examples/
45# Note: base32 charset uses bech32 charset
46function rpass {
47 cat /dev/urandom | LC_ALL=C tr -cd "qpzry9x8gf2tvdw0s3jn54khce6mua7l" | head -c ${1:-22}
48}
49
50
51#==Main Program==
52
53# Define $ENTROPY_BIT_COUNT1 as argument $1 or prompt user if $1 is not defined.
54# Note: argument test adapted from https://stackoverflow.com/a/6482403
55if [ -z "$1" ]
56then
57 echo "Entropy bit count argument (\$1) not supplied."
58 # Get from user the number of bits of entropy.
59 echoerr -n "Please specify the required strength of the password in bits of entropy (ex: 256):" # prompt via stderr
60 read ENTROPY_BIT_COUNT1
61else
62 ENTROPY_BIT_COUNT1="$1"
63fi
64
65# Check if $ENTROPY_BIT_COUNT1 is an non-negative integer
66# Note: Regular expression test is adapted from https://stackoverflow.com/a/806923
67RETEST1='^[0-9]+$'
68if ! [[ $ENTROPY_BIT_COUNT1 =~ $RETEST1 ]] ; then
69 echo "error: Not an integer." >&2; exit 1
70fi
71
72# Calculate minimum count of chars needed to encode $ENTROPY_BIT_COUNT1 with alphabet size of $ALPHABET_SIZE as float
73# Solve ln(a^n)/ln(2)=b for n using `bc` where
74# a=$ALPHABET_SIZE
75# n=$CHAR_COUNT1_FLOAT
76# b=$ENTROPY_BIT_COUNT1
77# Note: `bc` logarithm usage adapted from http://phodd.net/gnu-bc/bcfaq.html#bashlog
78CHAR_COUNT1_FLOAT=$(echo "$ENTROPY_BIT_COUNT1*l($LOG_BASE)/l($ALPHABET_SIZE)" | bc -l)
79# Note: Float will be of form "21.49744370650136860806".
80# Note: This particular example float should be rounded to "22" later.
81
82# Round $CHAR_COUNT1_FLOAT1 up to next highest integer for use as argument in later bash functions.
83# Note: awk expression from https://bits.mdminhazulhaque.io/linux/round-number-in-bash-script.html
84CHAR_COUNT1=$(echo "$CHAR_COUNT1_FLOAT" | awk '{print ($0-int($0)>0)?int($0)+1:int($0)}')
85
86# Generate passphrase
87PASS1=$(rpass "$CHAR_COUNT1")
88echo -e "$PASS1"
89
90
91#==References==
92#
93# - How to echo a string as stderr instead of stdout.
94# https://stackoverflow.com/a/2990533
95# Author: James Roth
96# Date: 2010-06-07T14:52Z
97# Date Accessed: 2020-01-20
98#
99# - How to check if script argument exists or not.
100# https://stackoverflow.com/a/6482403
101# Author: phoxix
102# Date: 2011-06-26T05:55Z
103# Date Accessed: 2020-01-20
104#
105# - How to check that a string is an integer using regular expression test.
106# https://stackoverflow.com/a/806923
107# Author: Charles Duffy
108# Date: 2009-04-30T13:32Z
109# Date Accessed: 2020-01-20
110#
111# - How to use `bc` to calculate logarithms in Bash
112# http://phodd.net/gnu-bc/bcfaq.html#bashlog
113# Author: unknown
114# Date Accessed: 2020-01-20
115#
116# - How to use `awk` to convert and round up a float to an integer.
117# https://bits.mdminhazulhaque.io/linux/round-number-in-bash-script.html
118# Author: Md. Minhazul Haque
119# Date: 2015-01-09
120# Date Accessed: 2020-01-20
121#
122# - How to use `/dev/urandom`, `tr`, and `head` to generate a random password in Bash.
123# https://www.thegeekstuff.com/2010/04/unix-bash-function-examples/
124# Author: SASIKALA, Ramesh Natarajan
125# Date: 2010-04-21
126# Date Accessed: 2020-01-20
127#
128# - Bech32 base32 charset
129# https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
130# Author: Pieter Wuille <pieter.wuille@gmail.com>
131# Date: 2017-03-20
132# License: BSD-2-Clause
133# Date: Accessed: 2021-01-23
134#
135# - Dependencies: bash, echo, bc, awk, tr, head.
136#
137# - GNU bash, version 5.0.3(1)-release (x86_64-pc-linux-gnu)
138# Copyright (C) 2019 Free Software Foundation, Inc.
139# License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
140# This is free software; you are free to change and redistribute it.
141# There is NO WARRANTY, to the extent permitted by law.
142#
143# - echo (GNU coreutils) 8.30
144# Copyright (C) 2018 Free Software Foundation, Inc.
145# License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
146# This is free software: you are free to change and redistribute it.
147# There is NO WARRANTY, to the extent permitted by law.
148#
149# Written by Brian Fox and Chet Ramey.
150#
151# - bc 1.07.1
152# Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
153#
154# - GNU Awk 4.2.1, API: 2.0 (GNU MPFR 4.0.2, GNU MP 6.1.2)
155# Copyright (C) 1989, 1991-2018 Free Software Foundation.
156#
157# This program is free software; you can redistribute it and/or modify
158# it under the terms of the GNU General Public License as published by
159# the Free Software Foundation; either version 3 of the License, or
160# (at your option) any later version.
161#
162# This program is distributed in the hope that it will be useful,
163# but WITHOUT ANY WARRANTY; without even the implied warranty of
164# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
165# GNU General Public License for more details.
166#
167# You should have received a copy of the GNU General Public License
168# along with this program. If not, see http://www.gnu.org/licenses/.
169#
170# - tr (GNU coreutils) 8.30
171# Copyright (C) 2018 Free Software Foundation, Inc.
172# License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
173# This is free software: you are free to change and redistribute it.
174# There is NO WARRANTY, to the extent permitted by law.
175#
176# Written by Jim Meyering.
177#
178# - head (GNU coreutils) 8.30
179# Copyright (C) 2018 Free Software Foundation, Inc.
180# License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
181# This is free software: you are free to change and redistribute it.
182# There is NO WARRANTY, to the extent permitted by law.
183#
184# Written by David MacKenzie and Jim Meyering.
203add48
SBS
185
186# Author: Steven Baltakatei Sandoval
187# License: GPLv3+