Find the answer to your Linux question:
Results 1 to 3 of 3
Well, not all that complex, but anyway I started making a password generator just for the challenge of it. I figured out most of what I want to do with ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Linux Newbie SagaciousKJB's Avatar
    Join Date
    Aug 2007
    Location
    Yakima, WA
    Posts
    162

    Specifying character amount in password generator.


    Well, not all that complex, but anyway I started making a password generator just for the challenge of it. I figured out most of what I want to do with it, but there's one portion of it confusing me and holding me back.

    Code:
    /*This program generates a password with no repeat characters, and allows the user to control the amount of each type of character in it*/
    //Kenneth Brown
    //2009
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <ctype.h>
    #include <malloc.h>
    #include <string.h>
    
    #define VALMAX 256
    
    void printSyntax(char arg[]);
    void stringGen(char *string, int stringLength);
    int grepString(char *string, char byte);
    
    struct optionStruct
    {
            int LCase;
            int UCase;
            int Sym;
            int Dig;
            int Verbosity;
            int Amount;
            int Seed;
            int Repeats;
    };
    
    struct optionStruct options;
    
    int main(int argc, char *argv[])
    {
            /*Let's allocate a buffer to store our generated string*/
            /*Since we're seeking to avoid repeats, the longest pass we can create will be 256 bytes*/
            char *passStorage = malloc(VALMAX);
            char randomByte;
            int i, seed = 0;
            int passLength;
            int Verbosity = 0;
    
            options.LCase = VALMAX;
            options.UCase = VALMAX;
            options.Dig = VALMAX;
            options.Sym = VALMAX;
    
            options.Seed = time(0);
    
            options.Amount = 1;
    
            if(argc == 1)
            {
                    printSyntax(argv[0]);
                    return 1;
            }
    
            /*Let's run through the command line options*/
            for(; argc > 1; argc--)
            {
                    if(strcmp("-v", argv[1]) == 0)
                            options.Verbosity = 1;
                    else if(strcmp("-h", argv[1]) == 0)
                    {
                            printSyntax(argv[0]);
                            return 1;
                    }
                    else if(strcmp("-a", argv[1]) == 0)
                            options.Amount = atoi(argv[2]);
                    else if(strcmp("-r", argv[1]) == 0)
                            options.Repeats = 1;
                    else if(strcmp("-s", argv[1]) == 0)
                    {
                            if(argv[2][0] == '-')
                                    options.Sym = 0;
                            else
                                    options.Sym = atoi(argv[2]);
                    }
                    else if(strcmp("-d", argv[1]) == 0)
                    {
                            if(argv[2][0] == '-')
                                    options.Dig = 0;
                            else
                                    options.Dig = atoi(argv[2]);
                    }
                    else if(strcmp("-l", argv[1]) == 0)
                    {
                            if(argv[2][0] == '-')
                                    options.LCase = 0;
                            else
                                    options.LCase = atoi(argv[2]);
                    }
                    else if(strcmp("-u", argv[1]) == 0)
                    {
                            if(argv[2][0] == '-')
                                    options.UCase = 0;
                            else
                                    options.UCase = atoi(argv[2]);
                    }
                   else if(strcmp("-S", argv[1]) == 0)
                   {
                            options.Seed = 0;
                            for(i = 0; (unsigned)i < strlen(argv[2]); i++)
                                    options.Seed += argv[2][i];
                    }
                    else if(strcmp("-L", argv[1]) == 0)
                    {
                            passLength = atoi(argv[2]);
                    }
    
                    for(i = 0; i < argc; i++)
                            argv[i] = argv[i + 1];
            }
    
            /*passLength = atoi(argv[0]);*/
            srand(options.Seed);
    
            for(i = 0; i < options.Amount; i++)
            {
                    /*Generate a password with enough entropy to be adequately secure*/
                    stringGen(passStorage, passLength);
    
                    /*Print a frequency analysis of password*/
                    if(options.Verbosity == 1)
                            freqAn(passStorage, passLength);
                    printf("%s\n", passStorage);
            }
    
            return 0;
    }
    
    int freqAn(char *string, int stringLength)
    {
            int ByteValue[VALMAX], Byte, i;
            int LCase = 0, UCase = 0, Dig = 0, Sym = 0;
            double FileSize = stringLength;
    
            /*Initialize ByteValue amounts to 0*/
    
            for(i = 0; i < VALMAX; i++)
            {
                    ByteValue[i] = 0;
            }
    
            for(i = 0; i < stringLength; i++)
            {
    
                    ByteValue[string[i]]++;
                    if(islower(string[i]) != 0)
                            LCase++;
                    if(isupper(string[i]) != 0)
                            UCase++;
                    if(isdigit(string[i]) != 0)
                            Dig++;
                    if(ispunct(string[i]) != 0)
                            Sym++;
    
            }
    
            for(i = 0; i < VALMAX; i++)
            {
                    if(ByteValue[i] != 0)
                    {
                            if( ((ByteValue[i] / FileSize) * 100) >= 10)
                            {
                                    fprintf(stderr,"%%%lf\t", (ByteValue[i] / FileSize) * 100);
                                    fprintf(stderr,"%i / %i\tD:%i\tH:%x\tA:\'%c\'\n", ByteValue[i], (int)FileSize, i, i, (char)i);
                            }
                            else
                            {
                                    fprintf(stderr,"%%0%lf\t", (ByteValue[i] / FileSize) * 100);
                                    fprintf(stderr,"%i / %i\tD:%i\tH:%X\tA:\'%c\'\n", ByteValue[i], (int)FileSize, i, i, (char)i);
                            }
                    }
            }
    
            printf("\n%i LCase %i UCase %i Digits %i Symbols\n\n", LCase, UCase, Dig, Sym);
    
    }
    
    void stringGen(char *string, int stringLength)
    {
            char randomByte;
            int i = 0;
    
            /*We make a Lower Case, Upper Case, Number, and Symbol counter variable*/
            int low = 0, upp = 0, num = 0, sym = 0;
    
            /*Wipe out previous string*/
            for(i = 0; i < VALMAX; i++)
                    string[i] = '\0';
    
    if(options.Repeats == 0)
    {
    
            for(i = 0; i < stringLength;)
            {
                    /*Get a random byte*/
                    randomByte = rand();
    
                    if(grepString(string, randomByte) == 0)
                    {
                            /*If randomByte does not already exist in string, is a printable character, and is not space*/
                            if(isprint(randomByte) != 0 && isspace(randomByte) == 0)
                            {
                                    string[i] = randomByte;
                                    i++;
    
                                    if(islower(randomByte) != 0)
                                    {
                                            if(low == options.LCase)
                                            {
                                                    i--;
                                                    string[i] = '\0';
                                            }
                                            else
                                                    low++;
                                    }
                                    else if(isupper(randomByte) != 0)
                                    {
                                            if(upp == options.UCase)
                                            {
                                                    i--;
                                                    string[i] = '\0';
                                            }
                                            else
                                                    upp++;
                                    }
                                    else if(isdigit(randomByte) != 0)
                                    {
                                            if(num == options.Dig)
                                            {
                                                    i--;
                                                    string[i] = '\0';
                                            }
                                            else
                                                    num++;
                                    }
                                    else if(ispunct(randomByte) != 0)
    
                                    {
                                            if(sym == options.Sym)
                                            {
                                                    i--;
                                                    string[i] = '\0';
                                            }
                                            else
                                                    sym++;
                                    }
                            }
    
                            /*low, upp, num and sym are checked to see if they are less than desired value*/
                            if(upp < options.UCase)
                            {
                                    /*This is looped until a desired character type is achieved*/
                                    while(1)
                                    {
                                            randomByte = rand();
                                            if(grepString(string, randomByte) == 0)
                                            {
                                                    if(isupper(randomByte) != 0)
                                                    {
                                                            string[i] = randomByte;
                                                            i++;
                                                            upp++;
                                                            break;
                                                    }
                                            }
                                    }
                            }
                            if(low < options.LCase)
                            {
                                    while(1)
                                    {
                                            randomByte = rand();
                                            if(grepString(string, randomByte) == 0)
                                            {
                                                    if(islower(randomByte) != 0)
                                                    {
                                                            string[i] = randomByte;
                                                            i++;
                                                            low++;
                                                            break;
                                                    }
                                            }
                                    }
                            }
                            if(num < options.Dig)
                            {
                                    while(1)
                                    {
                                            randomByte = rand();
                                            if(grepString(string, randomByte) == 0)
                                            {
                                                    if(isdigit(randomByte) != 0)
                                                    {
                                                            string[i] = randomByte;
                                                            num++;
                                                            i++;
                                                            break;
                                                    }
                                            }
                                    }
                            }
                            if(sym < options.Sym)
                            {
                                    while(1)
                                    {
                                            randomByte = rand();
                                            /*We need to also make sure that the character is not a space when using isprint*/
                                            if(grepString(string, randomByte) == 0)
                                            {
                                                    if(ispunct(randomByte) != 0 && isspace(randomByte) == 0)
                                                    {
                                                            string[i] = randomByte;
                                                            sym++;
                                                            i++;
                                                            break;
                                                    }
                                            }
                                    }
                            }
                    }
            }
    }
    else
    {
            for(i = 0; i < stringLength;)
            {
                    /*Get a random byte*/
                    randomByte = rand();
    
    
                            /*If randomByte does not already exist in string, is a printable character, and is not space*/
                            if(isprint(randomByte) != 0 && isspace(randomByte) == 0)
                            {
                                    string[i] = randomByte;
                                    i++;
    
                                    if(islower(randomByte) != 0)
                                    {
                                            if(low == options.LCase)
                                            {
                                                    i--;
                                                    string[i] = '\0';
                                            }
                                            else
                                                    low++;
                                    }
                                    else if(isupper(randomByte) != 0)
                                    {
                                            if(upp == options.UCase)
                                            {
                                                    i--;
                                                    string[i] = '\0';
                                            }
                                            else
                                                    upp++;
                                    }
                                    else if(isdigit(randomByte) != 0)
                                    {
                                            if(num == options.Dig)
                                            {
                                                    i--;
                                                    string[i] = '\0';
                                            }
                                            else
                                                    num++;
                                    }
                                    else if(ispunct(randomByte) != 0)
                                    {
                                            if(sym == options.Sym)
                                            {
                                                    i--;
                                                    string[i] = '\0';
                                            }
                                            else
                                                    sym++;
                                    }
                            }
    
                            /*low, upp, num and sym are checked to see if they are less than desired value*/
                            if(upp != options.UCase)
                            {
                                    /*This is looped until a desired character type is achieved*/
                                    while(1)
                                    {
                                            randomByte = rand();
                                                    if(isupper(randomByte) != 0)
                                                    {
                                                            string[i] = randomByte;
                                                            i++;
                                                            upp++;
                                                            break;
                                                    }
                                    }
                            }
                            if(low != options.LCase)
                            {
                                    while(1)
                                    {
                                            randomByte = rand();
                                                    if(islower(randomByte) != 0)
                                                    {
                                                            string[i] = randomByte;
                                                            i++;
                                                            low++;
                                                            break;
                                                    }
                                    }
                            }
                            if(num != options.Dig)
                            {
                                    while(1)
                                    {
                                            randomByte = rand();
                                                    if(isdigit(randomByte) != 0)
                                                    {
                                                            string[i] = randomByte;
                                                            num++;
                                                            i++;
                                                            break;
                                                    }
                                    }
                            }
                            if(sym != options.Sym)
                            {
                                    while(1)
                                    {
                                            randomByte = rand();
                                            /*We need to also make sure that the character is not a space when using isprint*/
                                                    if(ispunct(randomByte) != 0 && isspace(randomByte) == 0)
                                                    {
                                                            string[i] = randomByte;
                                                            sym++;
                                                            i++;
                                                            break;
                                            }
                                    }
                            }
            }
    
    }
    
            /*Cut string off at stringLength because it might be one byte over*/
            string[stringLength] = '\0';
    
    }
    
    int grepString(char *string, char byte)
    {
            int stringLength = 0;
            int i, boolean = 0;
    
            for(i = 0; string[i] != '\0'; i++)
                    stringLength++;
    
            for(i = 0; i < stringLength; i++)
            {
                    if(byte == string[i])
                    boolean++;
            }
    
            return boolean;
    }
    
    void printSyntax(char arg[])
    {
            printf("Usage:\t %s [-h | -v] [-a] [-r] [-S] [seed] [-l | -u | -d | -s ] -L passLength\n-h user for help\n-v for verbose \n-a for amount of passwords\n enable repeat characters\n-S use [seed] to seed prng\n -l -u -d -s\nlcase ucase digits and symbols respectively\nyou can disable each by invoking the switch alone\n or specify a maximum occurrence of each\n\nfor example\n %s -a 1000 -s 3 -l 1 -u 1 -d 3 -v -L 8\nwill generate 1000 passwords 8 characters long comprised of 3 symbols 1 lcase 1 ucase 3 digits and showing analysis of each one\n %s -a 1000 -s 0 -L 8\nsimply generates 1000 passwords each 8 characters long with no symbols\nwhile\n %s -s 4 -L 16\ncreates a pass with at most 4 symbols\n", arg, arg, arg, arg);
    }
    What I'm having problems with is the -l, -u, -d, and -s options. I wanted to create them originally so that the user could specify the exact amount of each, but really I've got it so convoluted now I don't really understand what they're doing.

    If I specify them all at the same time, like in the example, it will print the specified amount of each. However, if I leave one unspecified then the program seems to decide how much of each to use on its own. Stranger however, if I specify just one as zero, then it will leave that one out and still print the others fine.

    I think it has something to do with starting out the options.UCase and other structure members as 256, but if I start them out at 0 or 1 or even the length of the pass, then the program just infinite loops. However since if I specify them all and the math makes sense, it comes out exactly as I specified. The problem is how do I allow the user to omit one specification and have the program compensate and figure out what the rest need to be?

    There's probably a simple solution escaping me while I'm looking at the whole complex mess, but it's frustrating me because this shouldn't be so complicated.

  2. #2
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,664
    There is too much cruft to get into in detail, but you REALLY need to totally rework your argument list processing loop in main(). It isn't doing what you think. You might want to investigate using getopt() for this purpose.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  3. #3
    Linux Newbie SagaciousKJB's Avatar
    Join Date
    Aug 2007
    Location
    Yakima, WA
    Posts
    162
    Quote Originally Posted by Rubberman View Post
    There is too much cruft to get into in detail, but you REALLY need to totally rework your argument list processing loop in main(). It isn't doing what you think. You might want to investigate using getopt() for this purpose.
    Without getting into detail, could you mention briefly what is wrong with it? It seems to process and fill all values correctly when I run it through gdb, so it seems like it's doing everything I thought it would, and then something additional I'm not considering. I already checked getopt out and it looks like a better solution for sure ( standard and what not ), but I'm just curious about what I did wrong.

    Is there anything you can say about the stringGen() function though? I've looked over the code more and more, and the way I have it coded options.UCase, options.LCase, and the respective ones for digits and symbols seem to be acting more as limits than specific amounts to generate. If the sum of the "limits" equals the length of the string, then amounts of each will come out exactly as specified; however any other time it's unpredictable, except for '0' which successfully keeps it from generating characters of that type.

    The only problem with that is that they shouldn't be acting as limits and more as requirements because of the conditional statements like this one...

    Code:
    if(low < options.LCase)
                            {
                                    while(1)
                                    {
                                            randomByte = rand();
                                            if(grepString(string, randomByte) == 0)
                                            {
                                                    if(islower(randomByte) != 0)
                                                    {
                                                            string[i] = randomByte;
                                                            i++;
                                                            low++;
                                                            break;
                                                    }
                                            }
                                    }
                            }
    However, no matter what, if I specify only '-s 4' then I will get a "majority" of passwords that have 4, but then also many that have only 2 or 3. I think it's actually a problem with the loop producing more characters than stringLength, which is why I terminate the array at string[stringLength].

    So maybe if someone could point out to me what's wrong with the looping in stringGen() I could figure the rest out on my own.

  4. $spacer_open
    $spacer_close

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •