Date: Fri, 20 Nov 1998 23:01:12 +0100 From: Frank Nobis <fn@radio-do.de> To: freebsd-hackers@FreeBSD.ORG Subject: Re: Password generator Message-ID: <19981120230112.A10600@radio-do.de> In-Reply-To: <Pine.BSF.4.02A.9811201940440.7359-100000@korin.warman.org.pl>; from Andrzej Bialecki on Fri, Nov 20, 1998 at 07:42:55PM %2B0100 References: <00e501be14b4$e2c85080$09e3fecc@homepc> <Pine.BSF.4.02A.9811201940440.7359-100000@korin.warman.org.pl>
next in thread | previous in thread | raw e-mail | index | archive | help
--azLHFNyN32YCQGCU Content-Type: text/plain; charset=us-ascii On Fri, Nov 20, 1998 at 07:42:55PM +0100, Andrzej Bialecki wrote: > On Fri, 20 Nov 1998, Oleg Ogurok wrote: > > > > Hy, > > >I'm looking for a password generator. > > >Does anybody know where I can found one? > > > > > Well, you can look into a source code of DES, Kerberos, etc. > > Also, download Apache sources and look into "htpasswd" source. > > Hmmm.. I think he asked about something as routines present e.g. in SCO, > and used in their standard passwd(1) program - they are able to generate > passwords which are pronouncable (they even give example pronounciation), > but don't form any sensible word. > > Well, for now we don't have anything like this. > I have attached a simple source of such a password generator. I don't no where I first got it, but here it is. Regards Frank -- Frank Nobis Email: PGP AVAILABLE Landgrafenstr. 130 dg3dcn http://www.radio-do.de/~fn/ 44139 Dortmund Powered by SMP FreeBSD --azLHFNyN32YCQGCU Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="pwgen.c" /* * Generate (hopefully) pronounceable random passwords. These can often be * remembered more easily than completely random passwords, and are immune to * dictionary searches, etc. * * The original version of this program was written in BASIC on an OSI * Superboard II SBC. That version is long gone (the SB2's cassette drive * was never trustworthy, it eventually scrambled the tape), but the basic * (pardon the pun) idea lives on here, with a few modification like basing * the selection on "graphs" (actually, they are a restricted set of phonemes) * and having randomly-selected spellings for those graphs. */ #include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <math.h> #include <stdlib.h> #include <time.h> /* #define RANDOM(c) ((int) (rand(c) / 32767.0 * (c))) */ #ifdef linux #define RANDOM(c) ((int) (((random() & 0x7fffffff) / 2147483648.0) * (c))) #else #define RANDOM(c) ((int) (((random(c) & 0x7fff) / 32767.0) * (c))) #endif char *spelling[] = { /*a*/ "a", (char *) 0, /* 2*/ /*A*/ "a", "ae", "ai", (char *) 0, /* 6*/ /*b*/ "b", (char *) 0, /* 8*/ /*ch*/ "ch", (char *) 0, /*10*/ /*d*/ "d", (char *) 0, /*12*/ /*e*/ "e", (char *) 0, /*14*/ /*E*/ "e", "ee", "ie", (char *) 0, /*18*/ /*f*/ "f", "ph", "gh", (char *) 0, /*22*/ /*g*/ "g", (char *) 0, /*24*/ /*h*/ "h", (char *) 0, /*26*/ /*i*/ "i", "e", (char *) 0, /*29*/ /*I*/ "i", "ai", (char *) 0, /*32*/ /*i'*/ "i", "ei", (char *) 0, /*35*/ /*j*/ "j", "g", (char *) 0, /*38*/ /*k*/ "k", "c", (char *) 0, /*41*/ /*l*/ "l", (char *) 0, /*43*/ /*m*/ "m", (char *) 0, /*45*/ /*n*/ "n", (char *) 0, /*47*/ /*ng*/ "ng", (char *) 0, /*49*/ /*o*/ "o", "a", "ah", (char *) 0, /*53*/ /*O*/ "o", "oh", (char *) 0, /*56*/ /*oo*/ "oo", "u", (char *) 0, /*59*/ /*OO*/ "oo", "w", (char *) 0, /*62*/ /*p*/ "p", (char *) 0, /*64*/ /*qu*/ "qu", (char *) 0, /*66*/ /*r*/ "r", (char *) 0, /*68*/ /*s*/ "s", "c", (char *) 0, /*71*/ /*sh*/ "sh", "s", (char *) 0, /*74*/ /*t*/ "t", (char *) 0, /*76*/ /*th*/ "th", (char *) 0, /*78*/ /*TH*/ "th", (char *) 0, /*80*/ /*u*/ "u", (char *) 0, /*82*/ /*U*/ "u", "oo", (char *) 0, /*85*/ /*v*/ "v", (char *) 0, /*87*/ /*x*/ "x", (char *) 0, /*89*/ /*y*/ "y", (char *) 0, /*91*/ /*z*/ "z", "s", (char *) 0, /*94*/ }; struct graph { char *graph; char type; #define CONSONANT 0 #define VOWEL_LONG 1 #define VOWEL_SHORT 2 #define VOWEL_OTHER 3 #define VOWEL_MASK 3 #define iscons(c) (((c)->type & VOWEL_MASK) == 0) #define isvowel(c) (((c)->type & VOWEL_MASK) != 0) /* char frequency; */ /* unused for now */ char **spellings; /* struct graph **following; */ /* maybe later */ } graph[] = { {"a", VOWEL_SHORT, &spelling[0]}, {"A", VOWEL_LONG, &spelling[2]}, {"b", CONSONANT, &spelling[6]}, {"ch", CONSONANT, &spelling[8]}, {"d", CONSONANT, &spelling[10]}, {"e", VOWEL_SHORT, &spelling[12]}, {"E", VOWEL_LONG, &spelling[14]}, {"f", CONSONANT, &spelling[18]}, {"g", CONSONANT, &spelling[22]}, {"h", CONSONANT, &spelling[24]}, {"i", VOWEL_SHORT, &spelling[26]}, {"I", VOWEL_LONG, &spelling[29]}, {"i'", VOWEL_OTHER, &spelling[32]}, {"j", CONSONANT, &spelling[35]}, {"k", CONSONANT, &spelling[38]}, {"l", CONSONANT, &spelling[41]}, {"m", CONSONANT, &spelling[43]}, {"n", CONSONANT, &spelling[45]}, {"ng", CONSONANT, &spelling[47]}, {"o", VOWEL_SHORT, &spelling[49]}, {"O", VOWEL_LONG, &spelling[53]}, {"oo", VOWEL_SHORT, &spelling[56]}, {"OO", VOWEL_LONG, &spelling[59]}, {"p", CONSONANT, &spelling[62]}, {"qu", CONSONANT, &spelling[64]}, {"r", CONSONANT, &spelling[66]}, {"s", CONSONANT, &spelling[68]}, {"sh", CONSONANT, &spelling[71]}, {"t", CONSONANT, &spelling[74]}, {"th", CONSONANT, &spelling[76]}, {"TH", CONSONANT, &spelling[78]}, {"u", VOWEL_SHORT, &spelling[80]}, {"U", VOWEL_LONG, &spelling[82]}, {"v", CONSONANT, &spelling[85]}, {"x", CONSONANT, &spelling[87]}, {"y", CONSONANT, &spelling[89]}, {"z", CONSONANT, &spelling[91]}, {0, 0, &spelling[94]}, }; struct graph *vowel[] = { &graph[0], &graph[1], &graph[5], &graph[6], &graph[10], &graph[11], &graph[12], &graph[19], &graph[20], &graph[21], &graph[22], &graph[30], &graph[31], (struct graph *) 0, }; struct graph *consonant[] = { &graph[2], &graph[3], &graph[4], &graph[7], &graph[8], &graph[9], &graph[13], &graph[14], &graph[15], &graph[16], &graph[17], &graph[18], &graph[23], &graph[24], &graph[25], &graph[26], &graph[27], &graph[28], &graph[29], &graph[32], &graph[33], &graph[34], &graph[35], (struct graph *) 0, }; /* * Randomly select a graph from the specifield array. Eventually, this should * account for graph frequencies as well. */ struct graph *selgraph(graphs) struct graph **graphs; { register int cnt; for (cnt = 0; graphs[cnt] != (struct graph *) 0; cnt++) ; return graphs[RANDOM(cnt)]; } /* * Randomly select a spelling for the specified graph. This is not linear: * earlier spellings are preferred over later ones, but the latter do * sometimes sneak in. */ char *selspell(graph) struct graph *graph; { register int cnt, sel; for (cnt = 0; graph->spellings[cnt] != (char *) 0; cnt++) ; if (cnt == 0) { fprintf(stderr, "PANIC: selspell(%s) got count(spellings) == 0\n", graph->graph); exit(2); } if (cnt == 1) return *graph->spellings; /* * This may not be the best way to do it... maybe Weemba'd care to lend a * hand here? After all, my specialty is programming, NOT math. */ if ((sel = cnt - (int) sqrt((double) RANDOM(cnt * cnt) + 1) - 1) < 0 || sel >= cnt) { #ifdef BUGCATCH fprintf(stderr, "PANIC: selspell(%s) got nlrand(%d) == %d\n", graph->graph, cnt, sel); exit(2); #else sel = 0; #endif } return graph->spellings[sel]; } /* * Choose the next source for a graph. The rules are: a consonant MUST be * followed by a vowel; a vowel may be followed by a vowel of a different * type or by a consonant, but never more than two consecutive vowel graphs. */ char choosenext(cur, prev) { if (cur == CONSONANT) return VOWEL_MASK; else if (prev == -1 || (prev & VOWEL_MASK) != 0) return CONSONANT; else if (RANDOM(10) == 5) return VOWEL_MASK; else return CONSONANT; } /* * We are passed an array of (struct graph *); choose an entry randomly and * assemble a string fitting the size constraint. We use the original (OSI) * paradigm: alternate consonants and vowels, with the option of two vowels * in a row occasionally. The only difference is that they must be different * *types* of vowels, a distinction that the OSI version didn't consider. */ void pwgen(initial, pw, maxlen) struct graph **initial; char *pw; { int pwlen, state, prev, tmp; struct graph *graph; char *spelling; pwlen = 0; state = initial[0]->type; prev = -1; while (pwlen < maxlen - 1) { do { graph = selgraph(initial); } while (state != CONSONANT && graph->type == prev); if ((spelling = selspell(graph)) == (char *) 0) { fprintf(stderr, "PANIC: got NULL in selspell(%s)\n", graph->graph); exit(2); } strcpy(pw, spelling); while (*pw != '\0') pwlen++, pw++; tmp = prev; prev = graph->type; if ((state = choosenext(prev, tmp)) == CONSONANT) initial = consonant; else initial = vowel; } } int main(argc, argv) char **argv; { int cnt, len; char buf[20]; if (argc < 2 || argc > 3) { fprintf(stderr, "usage: %s length [count]\n", argv[0]); exit(1); } if ((len = atoi(argv[1])) < 4 || len > 16) { fprintf(stderr, "%s: invalid length %s\n", argv[0], argv[1]); exit(1); } if (argc == 2) cnt = 1; else if ((cnt = atoi(argv[2])) < 1) { fprintf(stderr, "%s: invalid count %s\n", argv[0], argv[2]); exit(1); } srandom(time(0) + (getpgrp() << 8) + getpid()); while (cnt-- != 0) { pwgen((RANDOM(10) < 4? vowel: consonant), buf, len); printf("%s\n", buf); } exit(0); } --azLHFNyN32YCQGCU-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19981120230112.A10600>