I am trying to build a random character generator in a bash script on osx 10.8.5 . The goal is to generate random character strings for a script generating salts for the wordpress wp-config.php
file. The snippet looks like the following:
#!/bin/bash -e
read -p "Number of digits: " digits
function rand_char {
take=$(($RANDOM % 88)); i=0; echo {a..z} {A..Z} {0..9} \, \; \. \: \- \_ \# \* \+ \~ \! \§ \$ \% \& \( \) \= \? \{ \[ \] \} \| \> \< | while read -d\ char;
do
[ "$i" = "$take" ] && echo "$char\c";
((i++));
done
}
function rand_string {
c=$1;
while [ $c -gt 0 ];
do char="${char}"$(rand_char);
let c=$c-1;
done
echo $char
}
outputsalt=`rand_string $digits`
echo $outputsalt
if i enter 64 as the number of digits the resulting number of characters differs each try:
HeF6D>z}x[v=s(qRoPmNkLiIfG7E5C3A1yZwWtU§S~Q*O_M:J,b86|4]2{0)X&p (63 chars)
WtUrSpQnOkLiJ,H8F6D4B1yZ)X&V$T!R+P_M:e;c9a7>5}2{u=s(q%o§m~j#hIfG (64 chars)
_g:d,b86|4]w{u=r&p$n!lMjKhIeFcDaB>z0xYt)r&p§m~kLiJgHeFcDA1yZwX (62 chars)
}w{u=s(q%oPmNkKhIfGdEbC3A1xYvWtUrS~Q*O_L.J,H8F6|4]2?Z)X&V$n!l+j_ (64 chars)
l+j_g:e;cDaB>z}x{u=sTqRoPmNkKhIfG7E5C3A1xYvW%U§S~Q*O_L.J,b86|4] (63 chars)
Is there a way that the number of characters sticks to the given number? Best regards Ralf
No offense, by your coding style is, errr..., not the best I've seen
:)
.Another way of doing this if you fancy one-liners:
or, as you probably won't want a new line at end:
Try a simpler case:
It will produce
a
and blanks, but nob
.We can further reduce the problem down to:
which only writes
a
and notb
. This is because you instructread
to read up to a space, and there's no space afterb
so it fails. This means that one out of every 88 chars will be dropped, causing your lines to be slightly shorter.The simplest fix is to add a dummy argument to force a space at the end:
Note that your method just adds 15 bits of entropy to the salt, while the absolute minimum should be 64. The significantly easier and more secure way of doing this would be:
(note: this replaces your unicode paragraph symbol with an ascii @)
I see two problems in your script.
I'm pretty sure
should be
Otherwise, it appears you're going past the end of your input stream.
The other problem is this char:
\§
Bash is seeing that as two characters (wide char?). I'd delete it from your possibilities.
Of course, that would mean the above line would be:
Doing those two things, in fact, works for me.
Edited:
@that other guy has a better answer. Adding the space rather than reducing the modulo will ensure that you get every character