gpw-0.0.19940601/0040755000175000017500000000000007305226604012712 5ustar frankiefrankiegpw-0.0.19940601/Makefile0100644000175000017500000000104306710724675014357 0ustar frankiefrankie# Makefile for password generator # THVV 6/1/94 # DEBUGARGS = -g COMPILER = gcc all : gpw loadtris echo gpw created, can delete loadtris gpw : gpw.o $(COMPILER) $(DEBUGARGS) -o gpw gpw.o trigram.h : loadtris ./loadtris /usr/dict/words | sed "s/, }/}/" > trigram.h gpw.o : gpw.c trigram.h $(COMPILER) $(DEBUGARGS) -o gpw.o -c gpw.c loadtris : loadtris.o $(COMPILER) $(DEBUGARGS) -o loadtris loadtris.o loadtris.o : loadtris.c $(COMPILER) $(DEBUGARGS) -o loadtris.o -c loadtris.c clean : rm gpw loadtris loadtris.o gpw.o # trigram.h gpw-0.0.19940601/LICENSE0100644000175000017500000000267207305226265013726 0ustar frankiefrankieCopyright (c) 2001, Tom Van Vleck All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Give me credit, and all the other pioneers, if you use the algorithms. 4. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. gpw-0.0.19940601/gpw.c0100644000175000017500000001125607305226407013656 0ustar frankiefrankie/* 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. This program uses "drand48()" to get random numbers, and "srand48()" to set the seed to the microsecond part of the system clock. Works for AIX C++ compiler and runtime. Might have to change this to port to another environment. 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 /* following for SysV. */ /* #include */ /* following for BSD */ #include 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 */ struct timeval systime; /* time reading for random seed */ struct timezone tz; /* unused arg to gettimeofday */ password_length = 8; /* Default value for password length */ n_passwords = 10; /* Default value for number of pws to generate */ gettimeofday (&systime, &tz); /* Read clock. */ srand48 (systime.tv_usec); /* 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); } gpw-0.0.19940601/loadtris.c0100644000175000017500000000745207305226470014705 0ustar frankiefrankie/* This program counts trigraphs in all the dictionaries specified and outputs a C++ include file of constants for gpw.C to use. Change to a C include file by changing "const" to "static." Output of this program needs postprocessing to eliminate comma closebrace, see the makefile for gpw. THVV 6/94 Coded */ #include "stdio.h" #include "stdlib.h" int tris[26][26][26]; /* Trigraph frequencies */ int duos[26][26]; /* Bigraph frequencies */ int sing[26]; /* Letter frequencies */ long max = 0; /* largest triraph count */ int m1, m2, m3; /* coords of largest count */ long sigma = 0; /* Total letters */ FILE *fp; int main (int argc, char ** argv) { char buf[100]; int j; int k1, k2, k3; int c1, c2, c3; char s1[2], s2[2], s3[2]; int argno, nfiles; for (c1=0; c1 < 26; c1++) { /* Initialize arrays to zero */ sing[c1] = 0; for (c2=0; c2 < 26; c2++) { duos[c1][c2] = 0; for (c3=0; c3 < 26; c3++) { tris[c1][c2][c3] = 0; } } } s1[1] = '\0'; s2[1] = '\0'; s3[1] = '\0'; nfiles = 0; /* count of files read */ if (argc < 2) { printf (" USAGE: loadtris /usr/dict/words ..."); exit (1); } for (argno = 1; argno < argc; argno++) { if ((fp = fopen (argv[argno], "r")) == NULL) { printf ("** file %s not found\n", argv[argno]); break; } nfiles++; while (fgets (buf, sizeof (buf), fp)) { j = 0; /* j indexes the input */ k2 = -1; /* k1, k2 are coords of previous letter */ k1 = -1; while (buf[j]) { /* until we find the null char.. */ k3 = buf[j]; /* Pick out a letter from the input */ if (k3 > 'Z') { k3 = k3 - 'a'; /* map from a-z to 0-25 */ } else { k3 = k3 - 'A'; /* map from A-Z to 0-25 */ } if (k3 >= 0 && k3 <= 25) { /* valid subscript? */ if (k1 >= 0) { /* do we have 3 letters? */ tris[k1][k2][k3]++; /* count */ sigma++; /* grand total */ if (tris[k1][k2][k3] > max) { max = tris[k1][k2][k3]; m1 = k1; /* note largest cell.. */ m2 = k2; /* .. for interest */ m3 = k3; } } if (k2 >= 0) { duos[k2][k3]++; /* count 2-letter pairs */ } sing[k3]++; /* count single letter frequency */ k1 = k2; /* shift over */ k2 = k3; } j++; } /* while buf[j] */ } /* while fgets */ fclose (fp); } /* for argno */ if (nfiles) { /* find any input? */ printf ("/* BEGIN INCLUDE FILE .. trigram.h */\n"); /* Multics style */ printf ("\n"); printf ("const long sigma = %ld;\n", sigma); /* (for my /usr/dict/words it is 125729, fits in a long) */ /* For interest print out the most frequent entry. */ /* (for my /usr/dict/words it is 863 = ATE, showing that a short works OK) */ s1[0] = m1 + 'a'; s2[0] = m2 + 'a'; s3[0] = m3 + 'a'; printf ("const short maxcell = %ld; /* %s%s%s */\n", max, s1, s2, s3); printf ("const short sing[26] = {"); for (c1=0; c1 < 26; c1++) { printf ("%d, ", sing[c1]); } printf ("};\n"); /* oops, ends in comma closebrace */ printf ("const short duos[26][26] = {"); for (c1=0; c1 < 26; c1++) { s1[0] = c1+'A'; printf ("\n{/* %s */ ", s1); for (c2=0; c2 < 26; c2++) { printf ("%d, ", duos[c1][c2]); } printf("}"); if (c1!=25) printf(","); } printf ("};\n"); /* oops, ends in comma closebrace */ printf ("const short tris[26][26][26] = {"); for (c1=0; c1 < 26; c1++) { printf("{"); for (c2=0; c2 < 26; c2++) { s1[0] = c1+'A'; s2[0] = c2+'A'; printf ("\n{/* %s %s */ ", s1, s2); for (c3=0; c3 < 26; c3++) { printf ("%d, ", tris[c1][c2][c3]); } printf("}"); if (c2!=25) printf(","); } printf("}"); if (c1!=25) printf(","); } printf ("};\n"); /* comma closebrace again, fix later */ printf ("/* END INCLUDE FILE .. trigram.h */\n"); } exit (0); } gpw-0.0.19940601/README0100644000175000017500000000235507305226362013575 0ustar frankiefrankieFssword Generator This password generator gives you a list of ten "pronounceable" passwords. It is modeled after Morrie Gasser's original generator described in * Gasser, M., A Random Word Generator for Pronouncable Passwords, MTR-3006, The Mitre Corporation, Bedford, MA 01730, ESD-TR-75-97, HQ Electronic Systems Division, Hanscom AFB, MA 01731. NTIS AD A 017676. except that Morrie's used a second-order approximation to English and this generator uses a third-order approximation. A descendant of Gasser's generator was added to the Multics operating system by Project Guardian in the mid 70s, and I believe Digital's VMS added a similar feature in the 80s. FIPS Standard 181 describes a similar digraph-based generator, derived from Gasser's.or details on gpw go to The first digraph-based password generator I know of was written by Daniel J. Edwards about 1965 for MIT's CTSS timesharing system. Understand that the passwords produced by this generator are only as "strong" as the initial source of randomness. Therefore, the best way to use this generator is to take its output and modify it in ways known only to you. Make some letters capital, or insert punctuation and numbers. http://www.multicians.org/thvv/gpw.html gpw-0.0.19940601/Makefile.Debian0100644000175000017500000000134707305226545015541 0ustar frankiefrankie# Makefile for password generator under Debian GNU/Linux # DEBUGARGS = -g COMPILER = gcc -Wall -O2 # Edited for Debian GNU/Linux DESTDIR= BIN=$(DESTDIR)/usr/bin all : gpw loadtris echo gpw created, can delete loadtris gpw : gpw.o $(COMPILER) $(DEBUGARGS) -o gpw gpw.o trigram.h : loadtris ./loadtris /usr/share/dict/words | sed "s/, }/}/" > trigram.h gpw.o : gpw.c trigram.h $(COMPILER) $(DEBUGARGS) -o gpw.o -c gpw.c loadtris : loadtris.o $(COMPILER) $(DEBUGARGS) -o loadtris loadtris.o loadtris.o : loadtris.c $(COMPILER) $(DEBUGARGS) -o loadtris.o -c loadtris.c clean : rm -f gpw loadtris loadtris.o gpw.o trigram.h # Modified for Debian GNU/Linux install: install -d $(DESTDIR) $(BIN) install -m 755 ./gpw $(BIN)