# 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$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.