1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
/* GPW - Generate pronounceable passwords
This program uses statistics on the frequency of three-letter sequences
in your dictionary to generate passwords. The statistics are in trigram.h,
generated there by the program loadtris. Use different dictionaries
and you'll get different statistics.
This program can generate every word in the dictionary, and a lot of
non-words. It won't generate a bunch of other non-words, call them the
unpronounceable ones, containing letter combinations found nowhere in
the dictionary. My rough estimate is that if there are 10^6 words,
then there are about 10^9 pronounceables, out of a total population
of 10^11 8-character strings. I base this on running the program a lot
and looking for real words in its output.. they are very rare, on the
order of one in a thousand.
The best way to use this program is to generate multiple words. Then
pick one you like and transform it with punctuation, capitalization,
and other changes to come up with a new password.
THVV 6/1/94 Coded
*/
#include "trigram.h"
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include <sys/types.h>
/* following for SysV. */
/* #include <bsd/sys/time.h> */
/* following for BSD */
#include <sys/time.h>
#include <limits.h>
long int pw_random_number(long int max_num);
int main (int argc, char ** argv) {
int password_length; /* how long should each password be */
int n_passwords; /* number of passwords to generate */
int pwnum; /* number generated so far */
int c1, c2, c3; /* array indices */
long sumfreq; /* total frequencies[c1][c2][*] */
double pik; /* raw random number in [0.1] from drand48() */
long ranno; /* random number in [0,sumfreq] */
long sum; /* running total of frequencies */
char password[100]; /* buffer to develop a password */
int nchar; /* number of chars in password so far */
password_length = 8; /* Default value for password length */
n_passwords = 10; /* Default value for number of pws to generate */
srand48 (pw_random_number(LONG_MAX)); /* Set random seed. */
if (argc > 1) { /* If args are given, convert to numbers. */
n_passwords = atoi (&argv[1][0]);
if (argc > 2) {
password_length = atoi (&argv[2][0]);
}
}
if (argc > 3 || password_length > 99 ||
password_length < 0 || n_passwords < 0) {
printf (" USAGE: gpw [npasswds] [pwlength]\n");
exit (4);
}
/* Pick a random starting point. */
/* (This cheats a little; the statistics for three-letter
combinations beginning a word are different from the stats
for the general population. For example, this code happily
generates "mmitify" even though no word in my dictionary
begins with mmi. So what.) */
for (pwnum=0; pwnum < n_passwords; pwnum++) {
pik = drand48 (); /* random number [0,1] */
sumfreq = sigma; /* sigma calculated by loadtris */
ranno = pik * sumfreq; /* Weight by sum of frequencies. */
sum = 0;
for (c1=0; c1 < 26; c1++) {
for (c2=0; c2 < 26; c2++) {
for (c3=0; c3 < 26; c3++) {
sum += tris[c1][c2][c3];
if (sum > ranno) { /* Pick first value */
password[0] = 'a' + c1;
password[1] = 'a' + c2;
password[2] = 'a' + c3;
c1 = c2 = c3 = 26; /* Break all loops. */
} /* if sum */
} /* for c3 */
} /* for c2 */
} /* for c1 */
/* Do a random walk. */
nchar = 3; /* We have three chars so far. */
while (nchar < password_length) {
password[nchar] = '\0';
password[nchar+1] = '\0';
c1 = password[nchar-2] - 'a'; /* Take the last 2 chars */
c2 = password[nchar-1] - 'a'; /* .. and find the next one. */
sumfreq = 0;
for (c3=0; c3 < 26; c3++)
sumfreq += tris[c1][c2][c3];
/* Note that sum < duos[c1][c2] because
duos counts all digraphs, not just those
in a trigraph. We want sum. */
if (sumfreq == 0) { /* If there is no possible extension.. */
break; /* Break while nchar loop & print what we have. */
}
/* Choose a continuation. */
pik = drand48 ();
ranno = pik * sumfreq; /* Weight by sum of frequencies for row. */
sum = 0;
for (c3=0; c3 < 26; c3++) {
sum += tris[c1][c2][c3];
if (sum > ranno) {
password[nchar++] = 'a' + c3;
c3 = 26; /* Break the for c3 loop. */
}
} /* for c3 */
} /* while nchar */
printf ("%s\n", password);
} /* for pwnum */
exit (0);
}
|