Commit | Line | Data |
---|---|---|
2feb5df8 | 1 | #!/bin/bash |
738ad68b SBS |
2 | # Desc: Generate passphrase with specified number of bits of entropy |
3 | # Usage: bknpass [integer] | |
4 | # Example: bknpass 256 | |
5 | # Result: 9tnzcl0m4dsm22a95525zj93jj | |
6 | # Version: 0.2.1 | |
7 | # Depends: bash 5.1.8, GNU coreutils 8.32, bc 1.07.1, awk 5.1.0 | |
8 | # License: | |
9 | # `bknpass`, an alphanumeric password generator | |
10 | # Copyright (C) 2022 Steven Baltakatei Sandoval (baltakatei.com) | |
11 | # | |
12 | # This program is free software: you can redistribute it and/or modify | |
13 | # it under the terms of the GNU General Public License as published by | |
14 | # the Free Software Foundation, either version 3 of the License, or | |
15 | # any later version. | |
16 | # | |
17 | # This program is distributed in the hope that it will be useful, | |
18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | # GNU General Public License for more details. | |
21 | # | |
22 | # A copy of the GNU General Public License may be found at | |
23 | # <https://www.gnu.org/licenses/>. | |
2feb5df8 | 24 | |
738ad68b SBS |
25 | yell() { echo "$0: $*" >&2; } # print script path and all args to stderr |
26 | die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status | |
27 | try() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails | |
28 | showUsage() { | |
29 | # Desc: Display script usage information | |
30 | # Usage: showUsage | |
31 | # Version 0.0.1 | |
32 | # Input: none | |
33 | # Output: stdout | |
34 | # Depends: GNU-coreutils 8.30 (cat) | |
35 | cat <<'EOF' | |
36 | USAGE: | |
37 | bknpass [int entropy_bit_count] | |
2feb5df8 | 38 | |
738ad68b SBS |
39 | EXAMPLE: |
40 | bknpass 128 | |
41 | EOF | |
42 | }; # Display information on how to use this script. | |
43 | main() { | |
44 | # Desc: main program | |
45 | # Usage: main "$@" | |
46 | # Input: $1: integer bits of entropy | |
47 | # Output: stdout: string passphrase | |
48 | # Depends: bash 5.1.8, GNU coreutils 8.32, bc 1.07.1, awk 5.1.0 | |
49 | # Ref/Attrib: [1] "Check existence of input argument in a Bash shell script". https://stackoverflow.com/a/6482403 | |
50 | # [2] "How do I test if a variable is a number in Bash?". https://stackoverflow.com/a/806923 | |
51 | # [3] "Round a Number in a Bash Script". https://bits.mdminhazulhaque.io/linux/round-number-in-bash-script.html | |
52 | # [4] "Logarithms in GNU bc". https://web.archive.org/web/20210211050732/http://phodd.net/gnu-bc/bcfaq.html#bclog | |
53 | # [5] "BIP 173". Note: bech32 charset. https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki | |
54 | # [6] "Bash Function to generate random password". https://www.thegeekstuff.com/2010/04/unix-bash-function-examples/ | |
55 | charset="qpzry9x8gf2tvdw0s3jn54khce6mua7l"; # bech32. See [5]. | |
56 | charset="$(tr -s "$charset" < <(echo -n "$charset"))"; # remove repeat chars | |
57 | alphabet_size="$(echo -n "$charset" | wc -c)"; # number of unique chars | |
58 | log_base=2; # entropy unit base (i.e. 2 for "bits of entropy") | |
2feb5df8 | 59 | |
738ad68b SBS |
60 | # Check inputs |
61 | if [[ $# -gt 1 ]]; then showUsage; die "ERROR:Too many arguments:$#"; fi; | |
2feb5df8 | 62 | |
738ad68b SBS |
63 | # Check for bc |
64 | if ! command -v bc 1>/dev/null 2>&1; then die "ERROR:bc not available"; fi; | |
2feb5df8 | 65 | |
738ad68b SBS |
66 | ## Get entropy_bit_count |
67 | if [[ -z "$1" ]]; then | |
68 | ### prompt user | |
69 | showUsage; | |
70 | echo -n "Please specify the required strength of the password in bits of entropy (ex: 256):" 1>&2; # prompt via stderr | |
71 | read -r entropy_bit_count | |
72 | else | |
73 | entropy_bit_count="$1"; | |
74 | fi; # See [1]. | |
2feb5df8 | 75 | |
738ad68b SBS |
76 | ## Check entropy_bit_count |
77 | pattern="^[0-9]+$"; | |
78 | if ! [[ $entropy_bit_count =~ $pattern ]] ; then die "ERROR:Not an integer:$entropy_bit_count"; fi; # See [2] | |
2feb5df8 | 79 | |
738ad68b SBS |
80 | ## Calculate minimum count of chars needed for passphrase as float using 'bc' |
81 | ### Solve ln(a^n)/ln(2)=b for n where: | |
82 | ### a=$alphabet_size | |
83 | ### n=$char_count_float | |
84 | ### b=$entropy_bit_count | |
85 | char_count_float="$(echo "$entropy_bit_count*l($log_base)/l($alphabet_size)" | bc -l)"; # See [4] | |
2feb5df8 | 86 | |
738ad68b SBS |
87 | ## Round $char_count_float to next highest integer |
88 | char_count="$(echo "$char_count_float" | awk '{print ($0-int($0)>0)?int($0)+1:int($0)}')"; # See [3] | |
2feb5df8 | 89 | |
738ad68b SBS |
90 | ## Generate and output passphrase |
91 | echo "$(LC_ALL=C tr -cd "$charset" < /dev/urandom | head -c "$char_count")"; # See [6] | |
92 | }; # main program | |
2feb5df8 | 93 | |
738ad68b | 94 | ( main "$@" ); # run 'main()' in subshell for 'die()' portability of script as sourced bash function. |
2feb5df8 SBS |
95 | |
96 | #==References== | |
97 | # | |
98 | # - How to echo a string as stderr instead of stdout. | |
99 | # https://stackoverflow.com/a/2990533 | |
100 | # Author: James Roth | |
101 | # Date: 2010-06-07T14:52Z | |
102 | # Date Accessed: 2020-01-20 | |
103 | # | |
104 | # - How to check if script argument exists or not. | |
105 | # https://stackoverflow.com/a/6482403 | |
106 | # Author: phoxix | |
107 | # Date: 2011-06-26T05:55Z | |
108 | # Date Accessed: 2020-01-20 | |
109 | # | |
110 | # - How to check that a string is an integer using regular expression test. | |
111 | # https://stackoverflow.com/a/806923 | |
112 | # Author: Charles Duffy | |
113 | # Date: 2009-04-30T13:32Z | |
114 | # Date Accessed: 2020-01-20 | |
115 | # | |
116 | # - How to use `bc` to calculate logarithms in Bash | |
117 | # http://phodd.net/gnu-bc/bcfaq.html#bashlog | |
118 | # Author: unknown | |
119 | # Date Accessed: 2020-01-20 | |
120 | # | |
121 | # - How to use `awk` to convert and round up a float to an integer. | |
122 | # https://bits.mdminhazulhaque.io/linux/round-number-in-bash-script.html | |
123 | # Author: Md. Minhazul Haque | |
124 | # Date: 2015-01-09 | |
125 | # Date Accessed: 2020-01-20 | |
126 | # | |
127 | # - How to use `/dev/urandom`, `tr`, and `head` to generate a random password in Bash. | |
128 | # https://www.thegeekstuff.com/2010/04/unix-bash-function-examples/ | |
129 | # Author: SASIKALA, Ramesh Natarajan | |
130 | # Date: 2010-04-21 | |
131 | # Date Accessed: 2020-01-20 | |
132 | # | |
133 | # - Bech32 base32 charset | |
134 | # https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki | |
135 | # Author: Pieter Wuille <pieter.wuille@gmail.com> | |
136 | # Date: 2017-03-20 | |
137 | # License: BSD-2-Clause | |
138 | # Date: Accessed: 2021-01-23 | |
139 | # | |
738ad68b | 140 | # - Dependencies: bash, bc, echo, awk, tr, head |
2feb5df8 | 141 | # |
738ad68b SBS |
142 | # - GNU bash, version 5.1.8(1)-release (x86_64-pc-linux-gnu) |
143 | # Copyright (C) 2020 Free Software Foundation, Inc. | |
2feb5df8 SBS |
144 | # License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> |
145 | # This is free software; you are free to change and redistribute it. | |
146 | # There is NO WARRANTY, to the extent permitted by law. | |
738ad68b SBS |
147 | # |
148 | # - bc 1.07.1 | |
149 | # Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc. | |
150 | # | |
151 | # - echo (GNU coreutils) 8.32 | |
152 | # Copyright (C) 2020 Free Software Foundation, Inc. | |
2feb5df8 SBS |
153 | # License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>. |
154 | # This is free software: you are free to change and redistribute it. | |
155 | # There is NO WARRANTY, to the extent permitted by law. | |
156 | # | |
157 | # Written by Brian Fox and Chet Ramey. | |
738ad68b SBS |
158 | # |
159 | # - GNU Awk 5.1.0, API: 3.0 (GNU MPFR 4.1.0, GNU MP 6.2.1) | |
160 | # Copyright (C) 1989, 1991-2020 Free Software Foundation. | |
161 | # | |
2feb5df8 SBS |
162 | # This program is free software; you can redistribute it and/or modify |
163 | # it under the terms of the GNU General Public License as published by | |
164 | # the Free Software Foundation; either version 3 of the License, or | |
165 | # (at your option) any later version. | |
738ad68b | 166 | # |
2feb5df8 SBS |
167 | # This program is distributed in the hope that it will be useful, |
168 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
169 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
170 | # GNU General Public License for more details. | |
738ad68b | 171 | # |
2feb5df8 SBS |
172 | # You should have received a copy of the GNU General Public License |
173 | # along with this program. If not, see http://www.gnu.org/licenses/. | |
174 | # | |
738ad68b SBS |
175 | # - tr (GNU coreutils) 8.32 |
176 | # Copyright (C) 2020 Free Software Foundation, Inc. | |
2feb5df8 SBS |
177 | # License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>. |
178 | # This is free software: you are free to change and redistribute it. | |
179 | # There is NO WARRANTY, to the extent permitted by law. | |
738ad68b | 180 | # |
2feb5df8 | 181 | # Written by Jim Meyering. |
738ad68b SBS |
182 | # |
183 | # - head (GNU coreutils) 8.32 | |
184 | # Copyright (C) 2020 Free Software Foundation, Inc. | |
2feb5df8 SBS |
185 | # License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>. |
186 | # This is free software: you are free to change and redistribute it. | |
187 | # There is NO WARRANTY, to the extent permitted by law. | |
738ad68b | 188 | # |
2feb5df8 | 189 | # Written by David MacKenzie and Jim Meyering. |