Simple password generator in Bash

December 11, 2007 | 22:58

Every time you need to create a password, you have to choose it well, that is you should use something which is very difficult to be guessed by anyone. In other words the password must be strong.
This article will tell when a password is considered a good one and how to automatically produce one with a simple bash script.

Three simple rules to obtain a strong password are:

  1. make it long;
  2. make it composed by characters which are choosen from a very big pool (alfanumeric ciphers is not enough!);
  3. don’t include anything related to you (birthdate, son’s name, etc.) or better: to anything.

The perfect password, then, is a long word made of strange characters choosen randomly. What’s better then, of an automatic random password generator?

Here is a very simple (but unsecure, don’t use it!) bash script that will generate a random word of the given length (default is 6 characters):

#!/bin/bash

charspool=('a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p'
'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7'
'8' '9' '0' 'A' 'B' 'C' 'D' 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' 'O'
'P' 'Q' 'R' 'S' 'T' 'U' 'V' 'W' 'X' 'Y' 'Z' '!' '£' '$' '%' '&' '=' '.' ',' ';' ':' '-' '_');

len=${#charspool[*]}

if [ $# -lt 1 ]; then
        num=6;
else
        num=$1;
fi

echo -n "password: "
for c in $(seq $num); do
        echo -n ${charspool[$((RANDOM % len))]}
done
echo

This code, that is very similar to the base64 algorithm, just extracts a number from $RANDOM bash variable and uses it to find the appropriate character in a fixed array (the pool).

In this case however, another problem emerges: how random is a number generated by a computer?
Well, in short the answer is that what we obtain from a computer is not a random (in fact it’s called pseudo-random) number but the event in which the same number is extracted by the modern pseudo-number generator (Bash’s one included) it’s stastically very rare.

The latter cannot be demonstrated without a full test of the generator. On the other hand, a quick proof that every generated number is just pseudo-random consists in seeding the generator with always the same seed:

$ RANDOM=1
$ for i in {1..10}; do echo -n "$RANDOM "; done; echo ""
16838 5758 10113 17515 31051 5627 23010 7419 16212 4086

This sequence is quite random, but if we reassign the value of 1 to $RANDOM we will obtain the same one again:

$ RANDOM=1
$ for i in {1..10}; do echo -n "$RANDOM "; done; echo;
16838 5758 10113 17515 31051 5627 23010 7419 16212 4086

In addition, when using a pseudo-random number generator for creating sensitive data such as passwords, we need to guarantee that nobody can recover the entire random sequence by knowing a part of it. It’s easily demonstrable that Bash pseudo-random number generator fails this property by allowing anyone to identify its internal state and thus all the precedent and subsequent random values by knowing a sequence of at least three values.

Moreover, every generator has a fixed length of these sequences after which it will repeat again from the begin; this length determines the quality of a pseudorandom number generator: the longer, the better.

A way to patch this problem is to re-seed the generator every tot numbers, each time with a different value; here is an example of how you do:

$ RANDOM=$(date '+%s')

Anyway, if you want to achieve a stronger randomness you should use /dev/urandom which comes directly from the kernel. Here is the previous script adapted to th

#!/bin/bash

charspool=('a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p'
'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7'
'8' '9' '0' 'A' 'B' 'C' 'D' 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' 'O'
'P' 'Q' 'R' 'S' 'T' 'U' 'V' 'W' 'X' 'Y' 'Z' '!' '£' '$' '%' '&' '=' '.' ',' ';' ':' '-' '_');

len=${#charspool[*]}

if [ $# -lt 1 ]; then
        num=6;

else
        num=$1;
fi
randomnumbers=$(head -c $num /dev/urandom | od -t u1 | awk '{for (i = 2; i <= NF; i++) print $i}')
echo -n "password: "
for c in $randomnumbers; do
        echo -n ${charspool[$((c % len))]}
done
echo

References:

Print This Post Print This Post
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

3 responses

TheBonsai | April 7, 2009 | 6:45

Avoid the seq-tool if possible:

1
for ((c = 1; c <=  num; c++)); do

mla | July 20, 2009 | 11:20

And here’s a one-liner version :) Same concept as yours except it’s using uuencode so it doesn’t include as much punctuation. So somewhat less secure.

function mkpw() { head /dev/urandom | uuencode -m – | sed -n 2p | cut -c1-${1:-8}; }

Колко сигурни за паролите, които ползваме? – BulTux | March 13, 2010 | 20:47

[...] Скриптът е взет от: My. Debian [...]

Leave a comment

You can use these tags : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>