/* dev-random-pass-gen: generation of user password with /dev/random Version: 1.1 - 2006-07-28 Original author: Thomas PORNIN (see below) Modifications by David MENTRE This program is in the Public Domain. Original author as provided his code as-is and don't want to hear of it (source: private communication). For any comment on this program, send them to David MENTRE. Reviews are welcome. Compile with: gcc -Wall -o dev-random-pass-gen dev-random-pass-gen.c Should work on any Un*x-like system. Run the program only once! Don't repeat it until you find an easy password as you would loose the randomness of this approach. */ #include #include #include #include #include /* return a random integer x in 0 <= x < max */ static unsigned randval(int rand_fd, unsigned max) { unsigned val; do { unsigned char x; for (;;) { if (read(rand_fd, &x, 1) <= 0) { if (errno == EINTR) continue; perror("read"); exit(EXIT_FAILURE); } break; } /* after this point: x has a random value such that 0 <= x < 256 */ val = x; } while (val >= max * (256 / max)); /* after this point: 0 <= val < max * |_ 256 / max _|. In other words, there is an integer k so that 0 <= val < max * k. So each integer n in 0 <= n < max has as much probability to be chosen by val. */ return val % max; } static int randletter(int rand_fd) { return "abcdefghijklmnopqrstuvwxyz"[randval(rand_fd, 26)]; } static int randdigit(int rand_fd) { return "0123456789"[randval(rand_fd, 10)]; } int main(void) { static int rand_fd = -1; /* we use /dev/random as it is supposed to be more secure than /dev/urandom and the blocking case is a non issue for manual password generation. */ rand_fd = open("/dev/random", O_RDONLY); if (rand_fd < 0) { perror("open"); exit(EXIT_FAILURE); } printf("%c%c%c%c%c%c%c%c%c%c\n", randletter(rand_fd), randletter(rand_fd), randdigit(rand_fd), randdigit(rand_fd), randletter(rand_fd), randletter(rand_fd), randdigit(rand_fd), randdigit(rand_fd), randletter(rand_fd), randletter(rand_fd)); /* Generated password has: log_2(26*26 * 10*10 * 26*26 * 10*10 * 26*26) > 41 bits of entropy If each password takes 1ms to test, it would take to try all passwords: 2^41 * 10e-3 / (3600 * 24 * 365) > 69 years */ close(rand_fd); return EXIT_SUCCESS; } /* The above program is a modification of following Usenet post. From: pornin@nerim.net (Thomas Pornin) Newsgroups: fr.misc.cryptologie Subject: Re: Quel logiciel libre de génération de mots de passe ? Date: Sun, 23 Jul 2006 11:39:33 +0000 (UTC) Message-ID: References: <87odw08nep.fsf@gmail.com> According to David MENTRE : > Je cherche un logiciel libre de génération aléatoire de mots de passe de > « bonne qualité ». Yakademander : =================================================================== #include #include #include #include #include #include #include static unsigned randval(unsigned max) { static int r = -1; unsigned char x; if (r < 0) { r = open("/dev/urandom", O_RDONLY); if (r < 0) { perror("open"); exit(EXIT_FAILURE); } } for (;;) { unsigned val; for (;;) { if (read(r, &x, 1) <= 0) { if (errno == EINTR) continue; perror("read"); exit(EXIT_FAILURE); } break; } val = (unsigned)x; if (val >= max * (256 / max)) continue; return val % max; } } static int randletter(void) { return "abcdefghijklmnopqrstuvwxyz"[randval(26)]; } static int randdigit(void) { return "0123456789"[randval(10)]; } int main(void) { printf("%c%c%c%c%c%c%c%c\n", randletter(), randletter(), randdigit(), randdigit(), randletter(), randletter(), randdigit(), randdigit()); return EXIT_SUCCESS; } =================================================================== Ça tourne sous Linux ou FreeBSD, ou n'importe quel autre unixoïde qui a un /dev/random. À chaque appel, ça génére un nouveau mot de passe de huit caractères : deux lettres minuscules, deux chiffres, deux lettres minuscules, deux chiffres. À l'usage, c'est assez facile à retenir. Entropie légèrement supérieure à 32 bits ; c'est suffisant pour la plupart des usages de mots de passe (c'est une question de protocole). Évidemment, l'entropie n'est atteinte que si on accepte le résultat. Si on fait tourner le programme plusieurs fois, jusqu'à obtenir un mot de passe "facilement mémorisable", alors on bousille l'entropie. --Thomas Pornin */