~ubuntu-branches/ubuntu/wily/gpw/wily

« back to all changes in this revision

Viewing changes to gpw.c

  • Committer: Bazaar Package Importer
  • Author(s): Francesco Paolo Lovergine
  • Date: 2002-03-11 17:09:10 UTC
  • Revision ID: james.westby@ubuntu.com-20020311170910-yp88kghgj83v1y5w
Tags: upstream-0.0.19940601
ImportĀ upstreamĀ versionĀ 0.0.19940601

Show diffs side-by-side

added added

removed removed

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