0

I need a way to generate a random password following this requirements:

  • Password at least 9 characters
  • at least 2 capital letters
  • at least 2 small letters
  • at least 2 digits
  • at least 2 special characters
  • must start with a letter

this is the command that I have:

{ shuf -r -n4 -e {A..Z}; shuf -r -n4 -e {a..z}; shuf -r -n4 -e {0..9}; } | shuf | tr -d $'\n'

but is missing the special characters

OS is SuSE 12

Greenonline
  • 1,851
  • 7
  • 17
  • 23

3 Answers3

0

Take a look at How to generate a random string?

herbert proposes using /dev/urandom

tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' </dev/urandom | head -c 13  ; echo

400 the Cat offers solution with openssl

openssl rand -base64 12

The problem is that none of those solutions guarantee that you'll have all the characters (i.e. 2 digits, 2 special characters etc.) that you want.

With shuf and based on your original code you can do something like

shuf -r -n1 -e {a..z} {A..Z} | tr -d $'\n'; { shuf -r -n2 -e {0..9}; shuf -r -n2 -e {a..z}; shuf -r -n2 -e {A..Z}; shuf -r -n2 -e { \! \" \# $ % \& '\' '/' \( \) \{ \} [ ] \< \> + - = . , : \; ? @ \| \` \~ ^ _ "'" \* }; } | shuf | tr -d $'\n'

Divided in lines for readability:

shuf -r -n1 -e {a..z} {A..Z} | tr -d $'\n'; 
{ shuf -r -n2 -e {0..9}; 
shuf -r -n2 -e {a..z}; 
shuf -r -n2 -e {A..Z}; 
shuf -r -n2 -e { \! \" \# $ % \& '\' '/' \( \) \{ \} [ ] \< \> + - = . , : \; ? @ \| \` \~ ^ _ "'" \* }; } | shuf | tr -d $'\n'

Which will produce a string starting with a letter (notice that I'm not piping first line into last shuf) and have 2 lowercase, 2 uppercase letters and 2 digits (a total of 9 characters)

golder3
  • 1,054
  • 1
  • 6
  • 15
  • thanks! now I have this (I removed some special characters not supported by my app) { shuf -r -n4 -e {A..Z}; shuf -r -n4 -e {a..z}; shuf -r -n4 -e {0..9}; shuf -r -n2 -e {$(sed -e 's/./& /g' <<< '@%+/!#$^?:.(){}[]-_.')}; } | shuf | tr -d $'\n';

    now the issue that I have is that numbers or special characters can not be the first character in the password, I can remove last shuf but this will have first all upper case, then all lowercase, then numbers and last the special characters, I need something like put at least 1 letter and then doesn't matter the order

    – Chris Sandoval Hidalgo Oct 27 '21 at 14:27
0

You could add the special characters with another shuf, just can't use brace expansion and ranges like that.

But you could explicitly list them, one by one, quoted to protect them from the shell:

shuf -r -n2 -e '!' '"' '#' '$' % '&' '(' ')' '*' + , - . / : ';' '<' = '>' '?' @ '[' '\' ']' '^' _ '{' '|' '}'

Or shove them in a string and use word-splitting to get them into multiple arguments. Need to disable globbing with set -f, though, otherwise the asterisk will cause issues:

set -f
shuf -r -n2 -e $(sed -e 's/./& /g' <<< '!"#$%&()*+,-./:;<=>?@[\]^_{|}' )

(or just do what everyone does, and add two fixed special characters at the end of an otherwise sensible password that's long enough even without them.)


To make sure you have a letter as the first character, it's easiest to just add one separately, and shuffle the characters of only the rest of the password. E.g. this would build the password in two pieces, the first being a single letter (upper or lower case), the second is what you had in the comments:

#!/bin/bash

set -f pw=$(shuf -r -n1 -e {A..Z} {a..z}) pw="$pw$( { shuf -r -n4 -e {A..Z}; shuf -r -n4 -e {a..z}; shuf -r -n4 -e {0..9}; shuf -r -n2 -e $(sed -e 's/./& /g' <<< '@%+/!#$^?:.(){}[]-_.'); } | shuf | tr -d '\n' )" echo "$pw"

The output would be something like this:

$ bash pw.sh 
WRgpJ7pP%Tj60.1
$ bash pw.sh 
oV6N#7s4Po3Bt)r
ilkkachu
  • 138,973
  • thanks! now I have this (I removed some special characters not supported by my app) { shuf -r -n4 -e {A..Z}; shuf -r -n4 -e {a..z}; shuf -r -n4 -e {0..9}; shuf -r -n2 -e {$(sed -e 's/./& /g' <<< '@%+/!#$^?:.(){}[]-_.')}; } | shuf | tr -d $'\n';

    now the issue that I have is that numbers or special characters can not be the first character in the password, I can remove last shuf but this will have first all upper case, then all lowercase, then numbers and last the special characters, I need something like put at least 1 letter and then doesn't matter the order

    – Chris Sandoval Hidalgo Oct 27 '21 at 14:27
  • @ChrisSandovalHidalgo, yep, see edit. Note that you don't need the braces around the command substitution: they'd be added as part of the arguments to shuf, it'd get {@, %, ... {, }, ... ., }. – ilkkachu Oct 27 '21 at 16:45
0

At the end, this is final command :

export PASSWORD=$(shuf -r -n1 -e {A..Z} {a..z})$( { shuf -r -n4 -e {A..Z}; shuf -r -n4 -e {a..z}; shuf -r -n4 -e {0..9}; shuf -r -n2 -e $(sed -e 's/./& /g' <<< '@%+\/!#$^?:.(){}[]-_.'); } | shuf | tr -d '\n' )
Greenonline
  • 1,851
  • 7
  • 17
  • 23