1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
# makepass
*This is a work in progress!*
I wrote `makepass` long ago to just spit out some random strings I could use as
passwords.
The first versions has been lost to time, and `makepass` was first commited to a
git-repo in 2018, as part of my dotfile-repo
[idgatt](https://git.dnns.no/idgatt/) ("It's Dangerous to Go Alone, Take
This!").
`makepass` was first written as a bash-script, but it was a zsh-script when I
commited it to my dotfile-repo. It was later changed back to a bash-script, and
in 2022 I rewrote it as both a POSIX shell-script and as a zsh-script.
Around then I found some joy in tinkering with the script, and I did some
optimalization of the zsh-script to minimilize forks and runtime. It is now pure
zsh, and does not fork out to any other programs.
Recently I decided I wanted to try to recreate makepass in other languages, and
maybe see if I can make it even faster.
## makepass specifications
Here's an attempt to specify how `makepass` should work. Might be useful for future versions.
`./makepass` is a symlink that points to whichever of the scripts I think is the best at any given time.
`makepass` should, by default, output:
- 10 "normal" passwords
- random characters from the "normal" character set (see below)
- 6 passwords with special characters
- first and last random character: alphanumerical
- the rest are random characters: from the "special" character set
- 6 passphrases put together from a wordlist the user can define (using
`/usr/share/dict/words` by default), separated by hyphens
If an (one) argument is supplied on the command line, it should be a number
between (including) 0 and 255, else an error should be shown. This argument
defines the length of the random passwords. If no argument is provided, every
password (not passphrase) should be of a random length between (including) 8
and 42 character
The passwords should *preferably* be output in columns. The number of columns
should be dynamic, and dependant on the width of the screen.
### Character sets
Normal character set: `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_`
Special character set: `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%&/()=?+-_,.;:<>[]{}|\@*`
### Example output
```
Normal passwords:
7B39aQZSm9P9BYZ8gBu0rLNIjNP SLztHlkZ5IsG5VaMfeF_JgttZOfZZa5
RxnvFtdztaX jZ6lAAA2a38ip5gwr_LuIDOys2Co
kn3hGdRMyIyz1sJic5iNL6N5 3Z9wWyScY4qqQYh
wigDZcuGDlWDyW4UKNtC_NHg9ITVfLOUq4Iq4R dJJSK10_SDk7q6Jk
41uPXf5d-jYCh7wgc0ZOy hTTcPdqGg5NWCyf7vcFp3su4kGQ0aIyP7xK7WVcp
Passwords with special characters:
p0M4b1%XP.BsIDH1ub[q9b+3nSR84!W$<e ZLz80iY]ZT%RcA*H
txX4e-vYf0ZO2hG20h[d Y!H0d1K4Vz*2z6U=?Yotk
hw!b;bK||[Bx gmrqB$nz[k!/fwV4>W%W
Passphrases:
brisk-gong-gag-open-life-boil
womb-nanny-stove-word-ajar-ocean
sage-barge-barge-five-poise-coach
lunar-juror-savor-unit-boil-sleep
cloth-nap-word-shun-gulp-sedan
guide-fray-dial-grid-candy-wick
```
## Benchmarks
I started out using just zshs `time` to time the runtime, but recently I started
checking out [hyperfine](https://github.com/sharkdp/hyperfine) which does a
nice job.
Here are the results so far:
```
% hyperfine --time-unit=millisecond --warmup=1 --shell=none ./makepass.*
Benchmark 1: ./makepass.bash
Time (mean ± σ): 422.7 ms ± 3.1 ms [User: 95.0 ms, System: 659.0 ms]
Range (min … max): 417.9 ms … 428.3 ms 10 runs
Benchmark 2: ./makepass.go
Time (mean ± σ): 6.9 ms ± 0.2 ms [User: 1.1 ms, System: 4.7 ms]
Range (min … max): 6.3 ms … 8.1 ms 434 runs
Benchmark 3: ./makepass.pl
Time (mean ± σ): 36.2 ms ± 0.4 ms [User: 17.8 ms, System: 16.2 ms]
Range (min … max): 35.6 ms … 37.9 ms 82 runs
Benchmark 4: ./makepass.sh
Time (mean ± σ): 1107.7 ms ± 15.3 ms [User: 276.0 ms, System: 1790.0 ms]
Range (min … max): 1084.9 ms … 1140.3 ms 10 runs
Benchmark 5: ./makepass.zsh
Time (mean ± σ): 25.3 ms ± 0.7 ms [User: 12.7 ms, System: 10.8 ms]
Range (min … max): 23.6 ms … 27.7 ms 114 runs
Summary
'./makepass.go' ran
3.69 ± 0.15 times faster than './makepass.zsh'
5.28 ± 0.17 times faster than './makepass.pl'
61.62 ± 1.86 times faster than './makepass.bash'
161.48 ± 5.22 times faster than './makepass.sh'
```
## Versions
### Bash
This version needs a bit more work.
### Go
Build width (from root folder in repo):
```
$ go build -o ../makepass.go -C go/ -ldflags "-s -w" makepass.go
```
### Perl
Perl version. I like this version.
### Shell
Needs more work.
### Zsh
This is currently the "main" version. It uses pure zsh, with no forking out to
other programs. As of adding the go-version, it is the second fastest version.
|