diff --git a/sourced/misc/password_generator/ReadMe.md b/sourced/misc/password_generator/ReadMe.md
index b98eab04..c056590e 100644
--- a/sourced/misc/password_generator/ReadMe.md
+++ b/sourced/misc/password_generator/ReadMe.md
@@ -1,6 +1,6 @@
# Nushell Password Generator "nupass"
-This nushell command randomly retrieves three words from a dictionary file (English with Japanese words added by @rickcogley) less than or equal to a given parameter's length, formats the words randomly with capitalization, then separates the words with some random symbols and numbers to return a password.
+This nushell command randomly retrieves a specified number of words from a dictionary file (English with Japanese words added by @rickcogley) less than or equal to a given parameter's length, formats the words randomly with capitalization, then separates the words with some random symbols and numbers to return a password.
To use:
@@ -20,10 +20,11 @@ http get https://raw.githubusercontent.com/RickCogley/jpassgen/master/genpass-di
let dictfile = $"/path/to/my/genpass-dict-jp"
```
-5. Confirm the symbols are what you want to use, and edit to taste:
+5. Confirm and edit the default symbols list and diceware delimiter:
```
-let symbolchars = "!@#$%^&*()_-+[]"
+--symbols (-s): string = "!@#$%^&()_-+[]{}" # Symbols to use in password
+--delimiter (-m): string = "-" # Delimiter for diceware
```
6. Load the script with `use` in your `config.nu`, something like:
@@ -40,12 +41,16 @@ Reload nu, then run it to test:
nupass -h
nupass 5
nupass 6 --debug
-nupass 3 -d
+nupass 8 -v diceware
+nupass 8 -v diceware -m _
+nupass 4 -v mixnmatch
+nupass 6 -v alphanum
+nupass 5 -l 8
```
### Testing
-If you're making changes to the script while testing, just re-source the script by doing:
+If you're making changes to the script while testing, you can just re-source the script by doing:
`use nupass.nu`
@@ -53,7 +58,7 @@ If you're making changes to the script while testing, just re-source the script
### Caveats
-I've been scripting for quite a long time, but not in nu. Input appreciated to make this more nu-esque!
+I've been scripting for quite a long time, but not in nu. Input appreciated to make this more nu-esque! The script is in a decent place as of the 20230501 version.
Obviously you can just use the `random chars` or `random integers` commands but I like to have words I can read in my passwords, and I think those generated by this script have sufficient entropy.
@@ -61,6 +66,7 @@ This command doesn't let you specify a precise length.
### Acknowledgements
-Thanks everyone on Discord for putting up with and answering my nubie questions @amtoine, @fdncred, @jelle, and for the feedback after try number 1.
+Thanks everyone on Discord for putting up with and answering my nubie questions @amtoine, @fdncred, @jelle, @sygmei, @kubouch and for the feedback after try number 1.
+
+
-
diff --git a/sourced/misc/password_generator/nupass.nu b/sourced/misc/password_generator/nupass.nu
index 331f50b1..49e58d04 100755
--- a/sourced/misc/password_generator/nupass.nu
+++ b/sourced/misc/password_generator/nupass.nu
@@ -1,15 +1,21 @@
# Script to generate a password from a dictionary file
# Author: @rickcogley
-# Thanks: @amtoine, @fdncred, @jelle
+# Thanks: @amtoine, @fdncred, @jelle, @sygmei, @kubouch
# Updates: 20230415 - initial version
# 20230416 - added @amtoine's slick probabilistic "random decimal" char capitalization
# 20230417 - added script duration output in debug block
# 20230421 - added length of symbol chars to get-random-symbol function
+# 20230422 - added variant flag to generate different styles of passwords
+# 20230501 - refactor to allow number of words to be specified, use list manipulation and reduce to string
#======= NUPASS PASSWORD GENERATOR =======
# Generate password of 3 dictionary file words, numbers and symbols
export def main [
- word_length: int = 4 # Max length of 3 words in password
+ words: int = 3 # Number of words in password
+ --word_length (-l): int = 5 # Max length of words in password
+ --symbols (-s): string = "!@#$%^&()_-+[]{}" # Symbols to use in password
+ --variant (-v): string = "regular" # Password style to generate in regular, mixnmatch, alphanum, alpha, diceware
+ --delimiter (-m): string = "-" # Delimiter for diceware
--debug (-d) # Include debug info
] {
##### Main function #####
@@ -23,18 +29,15 @@ export def main [
let num_lines = (open ($dictfile) | lines | wrap word | upsert len {|it| $it.word | split chars | length} | where len <= ($word_length) | length)
# Get random words from dictionary file
- let randword1 = ($dictfile | get-random-word $word_length $num_lines | random-format-word)
- let randword2 = ($dictfile | get-random-word $word_length $num_lines | random-format-word)
- let randword3 = ($dictfile | get-random-word $word_length $num_lines | random-format-word)
+ let random_words = (1..$words | each { |i| $dictfile | get-random-word $word_length $num_lines | random-format-word })
# Get some symbols to sprinkle like salt bae
- # Update symbol chars as needed
- let symbol_chars = "!@#$%^&()_-+[]{}"
- let symbol_chars_len = ($symbol_chars | str length)
- let symb1 = (get-random-symbol $symbol_chars $symbol_chars_len)
- let symb2 = (get-random-symbol $symbol_chars $symbol_chars_len)
- let symb3 = (get-random-symbol $symbol_chars $symbol_chars_len)
- let symb4 = (get-random-symbol $symbol_chars $symbol_chars_len)
+ # Update default symbol chars in symbols flag
+ let symbols_len = ($symbols | str length)
+ let random_symbols = (1..$words | each { |i| $symbols | get-random-symbol $symbols $symbols_len })
+
+ # Get some random numbers
+ let random_numbers = (1..$words |each { |i| (random integer 0..99) })
# Print some vars if debug flag is set
if $debug {
@@ -42,16 +45,34 @@ export def main [
print $"(ansi bg_blue) 🔔 Number of lines in dict with words under ($word_length) chars: (ansi reset)"
print $num_lines
print $"(ansi bg_blue) 🔔 Words from randomly selected lines: (ansi reset)"
- print $randword1 $randword2 $randword3
+ print $random_words
print $"(ansi bg_blue) 🔔 Randomly selected symbols: (ansi reset)"
- print $symb1 $symb2 $symb3 $symb4
+ print $random_symbols
+ print $"(ansi bg_blue) 🔔 Randomly selected numbers: (ansi reset)"
+ print $random_numbers
let endtime = (date now)
print $"(ansi bg_green) 🔔 Generated password in ($endtime - $starttime): (ansi reset)"
}
- # Return password
- return $"($symb1)(random integer 1..99)($randword1)($symb2)($randword2)($symb3)(random integer 1..99)($randword3)($symb4)"
-
+ # Return password in selected variant
+ if $variant == "regular" {
+ # Default variant, with regular distribution
+ # Generate new list w symbol, words, numbers, then reduce to string
+ return (0..($words - 1) | each { |it| ($random_symbols | get $it) + ($random_words | get $it) + ($random_numbers | get $it | into string) } | reduce { |it, acc| $acc + $it })
+
+ } else if $variant == "mixnmatch" {
+ # Combine lists, shuffle randomly, reduce to string
+ return (($random_words ++ $random_symbols ++ $random_numbers | shuffle) | reduce { |it, acc| ($acc | into string) + ($it | into string) })
+ } else if $variant == "alphanum" {
+ # Combined random int and random word, reduce to string
+ return (0..($words - 1) | each { |it| (random integer 0..99 | into string) + ($random_words | get $it) } | reduce { |it, acc| $acc + $it })
+ } else if $variant == "alpha" {
+ # Reduce random words only to string
+ return ($random_words | reduce { |it, acc| $acc + $it })
+ } else if $variant == "diceware" {
+ # Reduce to string with hyphen between words
+ return ($random_words | reduce { |it, acc| $acc + $"($delimiter)($it)" })
+ }
}
##### Utility functions #####
@@ -71,7 +92,7 @@ def get-random-word [
# Function to format a word randomly
def random-format-word [] {
- each {|it|
+ par-each {|it|
let rint = (random integer 1..4)
if $rint == 1 {
($it | str capitalize)