About
xkcd-style password generator
Features
- Balanced code verbosity, comments, documentation, tests, benchmarks, external dependencies
- CLI utility
- Rust library, function, macro
Usage
CLI
$ xpg -h
xpg 0.1.2
xkcd-style password generator
USAGE:
xpg [FLAGS] [OPTIONS]
FLAGS:
--analyze Analyze
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-c, --count <count> Number of passwords; default: 1
-w, --words <words> Number of words in password; default: 4
$ xpg -V
xpg 0.1.2
Examples
$ xpg
PeaceFirmWerePower
$ xpg -c 10
ColorSpringRingHall
AnotherCentLendDelaware
SureEveryTriedVowel
ConsiderLearnSendWave
JerusalemJoinRichHole
FarmExactlyStationGrew
DecimalForcePresidentsLater
EnjoyAppearGrownWood
OftenShallDirectionCourse
MayorGreeceCongoDecimal
$ xpg -w 8
SpeakAlongLaborGrassNailBattlePositionReach
$ xpg -w 8 -c 10
LostButterFellowWouldJoinedOfferEggsShine
StreamFlowYardCountGeneralEffectSecondLearn
SpeedGermanyCouldThinkMondayKissStrikeOctober
DearStationWentLikeAfricaPerhapsBeenWomen
CongoAgainstPlantEarlyGonePracticeAlabamaSail
HeavenUncleSuggestedNoiseBurningPassedEtchingTrust
FightColombiaJapanWillJoinedAgreedSentLabor
RiddenReachSubjectEnemyAfraidGroupCompanySuppose
NoneHouseBonesPastDressEffortBoatFellow
NailIrelandTestCowsScoreLikelyWheatWorth
$ xpg --analyze
* Word list length: 1,259
* Words in password: 4
* Total permutations (without repetition): 2,500,525,503,024
```
1,259! / (1,259 - 4)!
1,259! / 1,255!
2,500,525,503,024
```
Words | Permutations
---|---:
1 | 1,259
2 | 1,583,822
3 | 1,990,864,254
4 | 2,500,525,503,024
5 | 3,138,159,506,295,120
6 | 3,935,252,020,894,080,480
7 | 4,930,870,782,180,282,841,440
8 | 6,173,450,219,289,714,117,482,880
... | ...
$ xpg --analyze -w 8
* Word list length: 1,259
* Words in password: 8
* Total permutations (without repetition): 6,173,450,219,289,714,117,482,880
```
1,259! / (1,259 - 8)!
1,259! / 1,251!
6,173,450,219,289,714,117,482,880
```
Words | Permutations
---|---:
1 | 1,259
2 | 1,583,822
3 | 1,990,864,254
4 | 2,500,525,503,024
5 | 3,138,159,506,295,120
6 | 3,935,252,020,894,080,480
7 | 4,930,870,782,180,282,841,440
8 | 6,173,450,219,289,714,117,482,880
... | ...
Changelog
- 0.1.2 (2019-09-08)
- minor fixes
- 0.1.1 (2019-09-08)
- minor fixes
- 0.1.0 (2019-09-08)
- store wordlist as constant and operate on it without copying
- select N words without repetition via
choose_multiple - tests
- benchmark various implementations
xpgfunctionxpg!macro to enable optional word count argument- command line interface via clap
References
-

-
Word list comes from Bart Busschots' HSXKPasswd Perl module (GitHub, CPAN: Crypt::HSXKPasswd), specifically lib/Crypt/HSXKPasswd/Dictionary/EN.pm@1d88564:38
Tests
$ cargo test
running 11 tests
test tests::xpg_can_return_one_word ... ok
test tests::xpg_can_return_four_words ... ok
test tests::default_xpg_macro_returns_four_words ... ok
test tests::xpg_can_return_five_words ... ok
test tests::xpg_cannot_return_zero_words ... ok
test tests::xpg_can_return_three_words ... ok
test tests::xpg_macro_can_return_five_words ... ok
test tests::xpg_macro_cannot_return_zero_words ... ok
test tests::xpg_macro_can_return_four_words ... ok
test tests::xpg_macro_can_return_one_word ... ok
test tests::xpg_macro_can_return_three_words ... ok
test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Benchmarks
| Benchmark | time |
|---|---|
| 1 | 54.084 us 54.232 us 54.383 us |
| 2 | 191.25 ns 191.64 ns 192.26 ns |
| 3 | 190.73 ns 190.86 ns 191.03 ns |
Benchmark 1
let mut wordlist: = Vecnew;
for word in &WORDLIST
let p: = wordlist.choose_multiple
.cloned
.collect;
return p.join;
running 6 tests
test tests::default_xpg_returns_four_words ... ignored
test tests::xpg_can_return_five_words ... ignored
test tests::xpg_can_return_four_words ... ignored
test tests::xpg_can_return_one_word ... ignored
test tests::xpg_can_return_three_words ... ignored
test tests::xpg_cannot_return_zero_words ... ignored
test result: ok. 0 passed; 0 failed; 6 ignored; 0 measured; 0 filtered out
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Benchmarking xpg
Benchmarking xpg: Warming up for 3.0000 s
Benchmarking xpg: Collecting 100 samples in estimated 5.1942 s (96k iterations)
Benchmarking xpg: Analyzing
xpg time: [54.084 us 54.232 us 54.383 us]
Found 18 outliers among 100 measurements (18.00%)
1 (1.00%) low severe
16 (16.00%) high mild
1 (1.00%) high severe
Benchmark 2
let p: = WORDLIST.choose_multiple
.cloned.;
return p.join;
running 6 tests
test tests::default_xpg_returns_four_words ... ignored
test tests::xpg_can_return_five_words ... ignored
test tests::xpg_can_return_four_words ... ignored
test tests::xpg_can_return_one_word ... ignored
test tests::xpg_can_return_three_words ... ignored
test tests::xpg_cannot_return_zero_words ... ignored
test result: ok. 0 passed; 0 failed; 6 ignored; 0 measured; 0 filtered out
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Benchmarking xpg
Benchmarking xpg: Warming up for 3.0000 s
Benchmarking xpg: Collecting 100 samples in estimated 5.0002 s (24M iterations)
Benchmarking xpg: Analyzing
xpg time: [191.25 ns 191.64 ns 192.26 ns]
change: [-99.649% -99.648% -99.646%] (p = 0.00 < 0.05)
Performance has improved.
Found 6 outliers among 100 measurements (6.00%)
2 (2.00%) high mild
4 (4.00%) high severe
Benchmark 3
WORDLIST.choose_multiple
.cloned..join
running 6 tests
test tests::default_xpg_returns_four_words ... ignored
test tests::xpg_can_return_five_words ... ignored
test tests::xpg_can_return_four_words ... ignored
test tests::xpg_can_return_one_word ... ignored
test tests::xpg_can_return_three_words ... ignored
test tests::xpg_cannot_return_zero_words ... ignored
test result: ok. 0 passed; 0 failed; 6 ignored; 0 measured; 0 filtered out
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Benchmarking xpg
Benchmarking xpg: Warming up for 3.0000 s
Benchmarking xpg: Collecting 100 samples in estimated 5.0003 s (25M iterations)
Benchmarking xpg: Analyzing
xpg time: [190.73 ns 190.86 ns 191.03 ns]
change: [-0.5139% -0.1940% +0.1608%] (p = 0.27 > 0.05)
No change in performance detected.
Found 8 outliers among 100 measurements (8.00%)
2 (2.00%) high mild
6 (6.00%) high severe