ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
i've written a password generator in C, works just like i want it, has the GPL license, but i was wondering what you guys think of the way it is coded, what i could have done to improve the coding...
pwgenCL
here's the source:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void very_easy_password(int);
void very_easy2_password(int);
void easy_password(int);
void medium_password(int);
void hard_password(int);
void hard2_password(int);
void very_hard_password(int);
void extreme_password(int);
int main(int argc, char** argv)
{
int characterset=0;
int password_length=0;
if((argc<3)|(argc>3))
{
printf("\npwgenCL,commandline password generator, Copyright (C) 2004 Scorpius");
printf("\n\npwgenCL is free software; you can redistribute it and/or modify");
printf("\nit under the terms of the GNU General Public License as published by");
printf("\nthe Free Software Foundation; either version 2 of the License.");
printf("\n\npwgenCL is distributed in the hope that it will be useful,");
printf("\nbut WITHOUT ANY WARRANTY; without even the implied warranty of");
printf("\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the");
printf("\nGNU General Public License for more details.");
printf("\n\nYou should have received a copy of the GNU General Public License");
printf("\nalong with this program; if not, write to the Free Software");
printf("\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\n");
printf("\nCharacter sets:");
printf("\n1: (a-z)\t\t\t\t\tvery easy password");
printf("\n2: (A-Z)\t\t\t\t\tvery easy password");
printf("\n3: (a-z,A-Z)\t\t\t\t\teasy password");
printf("\n4: (a-z,0-9)\t\t\t\t\tmedium password");
printf("\n5: (A-Z,a-z,0-9)\t\t\t\thard password");
printf("\n6: (a-z,0-9, \\ ] [ ^ _ )\t\t\thard password");
printf("\n7: ( ! \" # $ % ' ( * ) + , - . / ,a-z,0-9)\tvery hard password");
printf("\n8: full keyboard characters (except space), almost impossible to crack\n\n");
printf("The maximum password length is 256 characters\n");
printf("Usage: %s <characterset> <password length>\n",argv[0]);
return 0;
}
if(argc==3)
{
characterset=atoi(argv[1]);
password_length=atoi(argv[2]);
if (password_length<1)
{
printf("Password length: %d is too small.\n",password_length);
return -1;
}
if (password_length>256)
{
printf("Password length: %d is too large.\n",password_length);
return -1;
}
switch(characterset)
{
case 1:
very_easy_password(password_length);
break;
case 2:
very_easy2_password(password_length);
break;
case 3:
easy_password(password_length);
break;
case 4:
medium_password(password_length);
break;
case 5:
hard_password(password_length);
break;
case 6:
hard2_password(password_length);
break;
case 7:
very_hard_password(password_length);
break;
case 8:
extreme_password(password_length);
break;
default:
printf("Invalid character set\n");
return -1;
break;
}
return 0;
}
else return -1;
}
/*(a-z) very easy password*/
void very_easy_password(length)
{
srand(time(NULL));
while (length>0)
{
int cha;
cha=rand()%128;
if((cha>=97 && cha<=122))
{
printf("%c",cha);
length--;
}
}
}
/* (A-Z) also very easy password */
void very_easy2_password(length)
{
srand(time(NULL));
while (length>0)
{
int cha;
cha=rand()%128;
if((cha>=65 && cha<=90))
{
printf("%c",cha);
length--;
}
}
}
/*(A-Z,a-z), easy password*/
void easy_password(length)
{
srand(time(NULL));
while (length>0)
{
int cha;
cha=rand()%128;
if((cha>=65 && cha<=90) || (cha>=97 && cha<=122))
{
printf("%c",cha);
length--;
}
}
}
/*(a-z,0-9) medium password*/
void medium_password(length)
{
srand(time(NULL));
while (length>0)
{
int cha;
cha=rand()%128;
if((cha>=48 && cha<=57) ||(cha>=97 && cha<=122))
{
printf("%c",cha);
length--;
}
}
}
/*(A-Z,a-z,0-9) hard password*/
void hard_password(length)
{
srand(time(NULL));
while (length>0)
{
int cha;
cha=rand()%128;
if((cha>=48 && cha<=57) || (cha>=65 && cha<=90) || (cha>=97 && cha<=122))
{
printf("%c",cha);
length--;
}
}
}
/*(a-z,0-9, \ ] [ ^ _ ) hard password*/
void hard2_password(length)
{
srand(time(NULL));
while (length>0)
{
int cha;
cha=rand()%128;
if((cha>=48 && cha<=57) || (cha>=91 && cha<=95) || (cha>=97 && cha<=122))
{
printf("%c",cha);
length--;
}
}
}
/*( ! " # $ % ' ( * ) + , - . / ,a-z,0-9) very hard password*/
void very_hard_password(length)
{
srand(time(NULL));
while (length>0)
{
int cha;
cha=rand()%128;
if((cha>=33 && cha<=57)|| (cha>=97 && cha<=122))
{
printf("%c",cha);
length--;
}
}
}
/*full keyboard characters (except space), almost impossible to crack */
void extreme_password(length)
{
srand(time(NULL));
while (length>0)
{
int cha;
cha=rand()%128;
if((cha>=33 && cha<=126))
{
printf("%c",cha);
length--;
}
}
}
(if you like the program, feel free to use it, it is opensource software)
void very_easy_password(length)
{
srand(time(NULL));
while (length>0)
{
int cha;
cha=rand()%128;
if((cha>=97 && cha<=122))
{
printf("%c",cha);
length--;
}
}
}
This looks horribly inefficient. I think it would be better to create the ability to always grab a valid character with rand(). You might want to consider setting up a character array that contains valid characters for each charset and then grabs a random character from that array. does that make sense?
Like, say for instance that one of your charsets creates a password consisting of lowercase characters, uppercase characters, and underscores.
ok, rand() is a bad idea because most stdlib's implementation of it is a first order lcg, ie a sequence of the form X_{n+1}=(a*X_n + c) mod m, which for this kind of thing is NOT good because
a) if some characters are known it is quite simple(cpu power wise) to narrow down possibilities of others, ie the generator has very low entropy.
b) some libc's (dont think glibc does) for speed take m to be a power of two because the modulus can be done with a bitwise and. this is DISASTEROUS when you do rand()%128 because its relativly simple to prove that given two sequences
X_n+1=a*X_n +c mod p*q
Y_n = X_n mod p
Y_n has a maximim period of p rather than p*q
so if you link with a libc like this passwords of more than 128 characters will repeat and most likely passwords of less will also repeat but thats dependant on a and c.
so you really shouldnt use rand() especially when there are cryptography libraries with far superior random number generators or the very well written (one of the best i think) entropy collectors that is /dev/random
your choice to disregard numbers although perhaps inefficient as stated by itsme86 is a good way of removing the structure of an lcg, especially in your context where the number of disregarded numbers is dependant only on the seed and the users choice of character set, this makes it much harder for a cracker to analyse passwords. and since today we have lots of cpu power and very large periods(in the region of 2^32) i would definatly stick with this if you inted to use rand() (obviously its a waste if you use /dev/random). if your interested it was first proposed by a guy called Todd in the mid 50s i think.
you do seem to have rather a lot of code repitition here, you need to do something like itsme86 was saying some kind of array, if your familiar with a bitmap i suggest you use something like that.
Code:
char x[128];
memset(x, 0, 128);
switch(charset) {
case 1:
memset(x+97, 1, 26);
break;
case 2:
memset(x+64, 1, 26);
break;
//...
//...
}
//then when generating
int i=rand()%128;
if(x[i]) printf("%c", x[i]);
as a final thought it might be a good idea to test your passwords before you pass them to the user by running them through something like cracklib.
<edit>
i dont know very much about seed choice other than you'll want it to be as unguessable as possible, which is why time(NULL) isnt the best, if the cracker knows the day the password is generated he only has 60*60*24 seeds to try which is a hell of a lot less than 2^32. as stated above sources of entropy are your best bet like /dev/random but you can make things difficult with badly behaved numerical systems such as chaotic dynamical systems or ill conditioned matrix equations
</edit>
well first of all, i've just started programming in C 2 months ago (i've started with C++ 1,5 years ago, but never gave it much thought), so most of the things you guys talk about i just haven't thought about or just don't know
but i'm surely gonna check all these points out, and perhaps in a couple of weeks, i can rewrite it with a much more effecient code
thanks a lot for the response
[edit]
ok, here's what i've come up with so far, i've also create an extra parameter to the code to create more randomness.
pwgenCL_2
Code:
/*
pwgenCL version 2 (pwgenCL_2)Copyright (C) 2004 Scorpius, password generator,
written as a command line scripting utility.
this program is freesource, which means you may use and/or modify it under the GPL license.
if you'd like to contact me with comments/bugs/suggestions or just to say hello,
my email address is: scorpius_unknown@yahoo.com.
i hope you enjoy using my program and that you find it usefull :)
to compile it under windows, get a copy of Dev-C++ (it's free), or another C/C++ compiler.
to compile it under linux, just type "gcc -o pwgenCL_2 pwgenCL_2.c" (without the " quotes)
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <strings.h>
char *generated_password(char*, int,int);
int main(int argc, char** argv)
{ /*the character sets*/
char *very_easy_set = "abcdefghijklmnopqrstuvwxyz";
char *very_easy2_set = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *easy_set = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *medium_set = "abcdefghijklmnopqrstuvwxyz0123456789";
char *hard_set = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
char *hard2_set = "\\][^_abcdefghijklmnopqrstuvwxyz0123456789";
char *very_hard_set = "!\"#$%'(*)+,-./abcdefghijklmnopqrstuvwxyz0123456789";
char *extreme_set = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
int characterset=0;
int password_length=0;
int user_supplied=0;
if(argc!=4)
{
printf("\npwgenCL_2,commandline password generator, Copyright (C) 2004 Scorpius");
printf("\n\npwgenCL_2 is free software; you can redistribute it and/or modify");
printf("\nit under the terms of the GNU General Public License as published by");
printf("\nthe Free Software Foundation; either version 2 of the License.");
printf("\n\npwgenCL_2 is distributed in the hope that it will be useful,");
printf("\nbut WITHOUT ANY WARRANTY; without even the implied warranty of");
printf("\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the");
printf("\nGNU General Public License for more details.");
printf("\n\nYou should have received a copy of the GNU General Public License");
printf("\nalong with this program; if not, write to the Free Software");
printf("\nFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n");
printf("\n\t ***Contact Scorpius: scorpius_unknown@yahoo.com***");
printf("\n\nCharacter sets:");
printf("\n1: (a-z)\t\t\t\t\tvery easy password");
printf("\n2: (A-Z)\t\t\t\t\tvery easy password");
printf("\n3: (a-z,A-Z)\t\t\t\t\teasy password");
printf("\n4: (a-z,0-9)\t\t\t\t\tmedium password");
printf("\n5: (A-Z,a-z,0-9)\t\t\t\thard password");
printf("\n6: (a-z,0-9, \\ ] [ ^ _ )\t\t\thard password");
printf("\n7: ( ! \" # $ % ' ( * ) + , - . / ,a-z,0-9)\tvery hard password");
printf("\n8: full keyboard characters (except space), almost impossible to crack\n\n");
printf("The maximum password length is 256 characters\n");
printf("Usage: %s <characterset> <password length> <user supplied number>\n",argv[0]);
printf("\n*The <user supplied number> is inserted to create extra randomness*\n");
printf("\nExample: %s 8 15 5454303\n",argv[0]);
return 0;
}
if(argc==4)/*if all parameters, (characterset,passwordlength,randomization number) run the program*/
{
characterset=atoi(argv[1]);/*create integer from the argument*/
password_length=atoi(argv[2]);/*create integer from the argument*/
user_supplied=atoi(argv[3]);/*create integer from the argument*/
if (password_length<1)
{
printf("Password length: %d is too small.\n",password_length);
return -1;
}
if (password_length>256)
{
printf("Password length: %d is too large.\n",password_length);
return -1;
}
switch(characterset)
{
case 1:
generated_password(very_easy_set,password_length,user_supplied);
break;
case 2:
generated_password(very_easy2_set,password_length,user_supplied);
break;
case 3:
generated_password(easy_set,password_length,user_supplied);
break;
case 4:
generated_password(medium_set,password_length,user_supplied);
break;
case 5:
generated_password(hard_set,password_length,user_supplied);
break;
case 6:
generated_password(hard2_set,password_length,user_supplied);
break;
case 7:
generated_password(very_hard_set,password_length,user_supplied);
break;
case 8:
generated_password(extreme_set,password_length,user_supplied);
break;
default:
printf("Invalid character set\n");
return -1;
break;
}
return 0;
}
else return -1;
}
/*the password generator function*/
char *generated_password(char* char_set, int length,int user_number)
{
srand(user_number*time(NULL));
int loop;
int set_length=strlen(char_set);
for(loop=0;loop<length;loop++)
{
putchar(char_set[rand()%set_length]);
}
printf("\n");
}
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.