I know there are lots of examples out there for password scripts, but I haven't found a good one that generates good human readable passwords. Here is what I am up against.
1 Must use at least 14 characters,
2 Must include a mix of the four classes of characters i.e UPPER, lower, number, and special.
3 Must not allow any one class of character to appear more than 3 in a row.
4 Must not allow the password to contain any sequence of the user id.
A number 3 example: ABC is good, ABCD is not. 123 is good, 1234 is not. #$% is good, #$%^ is not. I think you get the point.
I think with number 4 I can use some sort of $USER environment variable or getent passwd
CONTROL C MOMENT: if you know of one, please read no more and send me the link.
To handle the human readable element I, up front, establish certain rules about character substitution. Here are a few I have come up with:
In a set of three letters, if all are lower, one will be force to upper.
The letter "A" or "a" can be "A", "a", or "@"
The letter "B" or "b" can be "B", "b", "6", or "%"
The letter "O" or "o" can be "O", "o", or "0" (that is a zero)
The letter "I" or "i" can be "I", "i", "!" "1" or "|"
Again you get the point. Establish some rules about letter substitution.
I have already did a small script and extracted every fourteen character password from /usr/share/dict/linux.words, there was 19326 of them. (My OS is RHEL 6). Perhaps I should have gotten 14 and above, but I can do that later.
My script currently uses bashes $RANDOM to pick a word from that 19326 word list.
I just ran my script and got "arthrogryoosis" Now I have to translate it and the end result I would want would be something like: Ar+hr0&rOo51s. The a is upper, the t became a +, one o became a 0 (zero), the g became a &, one o went to upper, one s became a 5, etc etc.
The key is you start with a human readable password. Then my users understand the translation rules, and then they take the given translation and easily remember it because the know they rules. After a few days of typing it, it will become mechanical for them.
You are wondering -- where is he going with this. Thank you for your patience and here is where I need the input of the gurus.
I am currently handling the translation character by character. My script contains a function that is getting rather large like this:
function convertletter {
# Handle the letter S.
#### Or try SPECIALforS='S s $ 5'
SPECIALforS='$ 5'
specialforS=($SPECIALforS)
num_specialforS=${#specialforS[*]}
I have already, earlier in the script used cut to get each character i.e C1, C2, ... C14
C1=`cut -c 1 /tmp/modnar` (The word is in a tmp file, modnar is random backwards.)
...
C14=`cut -c 14 /tmp/modnar`
Now I use an if statement to translate the character randomly.
# Just force the first letter to upper. Find a better way later. This is not a good rule.
if [[ $C1 == [a-z] ]] ; then
P1=`echo $C1 | tr '[:lower:]' ':[upper]:'`
fi
# What if the second character is an S or s?
if [[ $C2 == [Ss] ]] ; then
# Randomly choose a $, or 5
P2=`echo ${specialforS[$((RANDOM%num_specialforS))]}'
else
P2=$C2
fi
Latter on I will echo out $P1 $P2 ... $P14 for the user to see, learn, remember and then it will be deleted and gone forever.
So here is where I need ideas. As you can see scripting each character in each of 14 positions can get very long. C2 can also include any of the vowels, and a number of the consonants. And setting up all those small arrays to handle each of the possibilities for the 14 different positions might be a nightmare.
And I haven't even gotten to checking for a sequence of three.
I know this, at least to me, seems like a daunting task, but if you have any ideas, I'd love your input.
Let me know if you need more input.
Blessings to all.