]> src.twobees.de Git - dotfiles.git/blob - stow/oh-my-zsh/.oh-my-zsh/plugins/genpass/genpass-apple
initial
[dotfiles.git] / stow / oh-my-zsh / .oh-my-zsh / plugins / genpass / genpass-apple
1 #!/usr/bin/env zsh
2 #
3 # Usage: genpass-apple [NUM]
4 #
5 # Generate a password made of 6 pseudowords of 6 characters each
6 # with the security margin of at least 128 bits.
7 #
8 # Example password: xudmec-4ambyj-tavric-mumpub-mydVop-bypjyp
9 #
10 # If given a numerical argument, generate that many passwords.
11
12 emulate -L zsh -o no_unset -o warn_create_global -o warn_nested_var
13
14 if [[ ARGC -gt 1 || ${1-1} != ${~:-<1-$((16#7FFFFFFF))>} ]]; then
15   print -ru2 -- "usage: $0 [NUM]"
16   return 1
17 fi
18
19 zmodload zsh/system zsh/mathfunc || return
20
21 {
22   local -r vowels=aeiouy
23   local -r consonants=bcdfghjklmnpqrstvwxz
24   local -r digits=0123456789
25
26   # Sets REPLY to a uniformly distributed random number in [1, $1].
27   # Requires: $1 <= 256.
28   function -$0-rand() {
29     local c
30     while true; do
31       sysread -s1 c || return
32       # Avoid bias towards smaller numbers.
33       (( #c < 256 / $1 * $1 )) && break
34     done
35     typeset -g REPLY=$((#c % $1 + 1))
36   }
37
38   local REPLY chars
39
40   repeat ${1-1}; do
41     # Generate 6 pseudowords of the form cvccvc where c and v
42     # denote random consonants and vowels respectively.
43     local words=()
44     repeat 6; do
45       words+=('')
46       repeat 2; do
47         for chars in $consonants $vowels $consonants; do
48           -$0-rand $#chars || return
49           words[-1]+=$chars[REPLY]
50         done
51       done
52     done
53
54     local pwd=${(j:-:)words}
55
56     # Replace either the first or the last character in one of
57     # the words with a random digit.
58     -$0-rand $#digits || return
59     local digit=$digits[REPLY]
60     -$0-rand $((2 * $#words)) || return
61     pwd[REPLY/2*7+2*(REPLY%2)-1]=$digit
62
63     # Convert one lower-case character to upper case.
64     while true; do
65       -$0-rand $#pwd || return
66       [[ $vowels$consonants == *$pwd[REPLY]* ]] && break
67     done
68     # NOTE: We aren't using ${(U)c} here because its results are
69     # locale-dependent. For example, when upper-casing 'i' in Turkish
70     # locale we would get 'İ', a.k.a. latin capital letter i with dot
71     # above. We could set LC_CTYPE=C locally but then we would run afoul
72     # of this zsh bug: https://www.zsh.org/mla/workers/2020/msg00588.html.
73     local c=$pwd[REPLY]
74     printf -v c '%o' $((#c - 32))
75     printf "%s\\$c%s\\n" "$pwd[1,REPLY-1]" "$pwd[REPLY+1,-1]" || return
76   done
77 } always {
78   unfunction -m -- "-${(b)0}-*"
79 } </dev/urandom