timj/perl-Crypt-PassGen — pull request #1 by VadimPushtaev (2012-09-21 11:52:12+00:00)
Title: Insufficient length of password bug fixed

# Problem

```
time perl -e 'use Crypt::PassGen;
do {
($p) = Crypt::PassGen::passgen( NWORDS => 1, NLETT => 8 );
} while 8 == length $p;
print $p'
partijk
real 25m13.003s
user 24m53.170s
sys 0m0.098s
```

As you can see, we can sometimes get password with length lesser than NLETT, that is a really awful bug.

# Workaround

Now we use something like

```
while( length( $pass ) < $len )
{
( $pass ) = Crypt::PassGen::passgen( NWORDS => 1, NLETT => $len );
}
```

Make me unsee it.

# Reason

We have a problem with this piece of code:

```
for my $i ( 3.. $nlett ) {
$ind = _tot_to_index( int(rand( $data->{PAIR_TOT}[$prev1][$prev2] )),
$data->{THIRD}[$prev1][$prev2] );
next WORDLOOP if $ind < 0;
$score += $data->{THIRD}[$prev1][$prev2][$ind];
$word .= $revlett{ $ind };
$prev1 = $prev2; # store the previous two letters
$prev2 = $ind;
}
```

We can drop iteration (because `_tot_to_index()` returns a negative number) before `$word`'s length becomes `$nlett`, but sometimes (very rare) `$score` is already `> $minscore`, so we finish the loop.

# Fix

We can check whether `$word` has enough chars in it or it doesn't to finish the loop.

# Note

I assumed that is all about that `if`:

```
if ($n > 100) {
$n = 0;
$minscore *= 0.75;
}
```

But it's not. In truth, we made about ten million of password and didn't get `$n > 100` not even once.