Search code examples
cstringcs50string-literalscrypt

How to compare the output of crypt() to a cmd line input for cracking passwords in C


I'm taking the cs50x intro to comp sci course and one of the exercises is to decrypt a password that was encrypted using the crypt(3) function.

They've simplified the requirements by setting the hypothetical that the password can only be 5 characters long and every character will be an uppercase or lowercase letter.

I've hit a roadblock with encrypting and comparing and am unsure how to move forward.

Summary below.

I've made it as far as cycling through all possible variations of A-Z and a-z for A, AA, AAA, AAAA, and AAAAA.

And I can compare that to user input from argv.

Now I'm trying to have argv be a hash and compare that to the hash of ( possible password from above)

Where I'm struggling -->

How I imagine the code should work

  1. receive argv[1] and identify salt.
  2. generate password
  3. hash password with crypt()
  4. compare password-hash vs argv[1]
  5. if not a match, generate new password and repeat until match.

What's not working -->

storing the password hash for comparison and updating the password hash with new hash after manipulation.

What I think I understand -->

  1. The hash is stored as a string literal.
  2. You can't update string literals.
  3. I need to assign a variable to store the hash in order to compare it to argv.

What am I missing? What should I read up on to move forward?

thanks in advance!


Solution

  • You can assign the result of crypt(3) to a char* and reference the hash from the pointer:

    char *compare = crypt(p, salt);
    compare = crypt(p, salt);
    

    Since crypt(3) has its own static data space it will rewrite on every call to it, you may want to copy the hash to your program's space using a char array and strcpy(3)

    char hash[256]; // arbitrary length, enough to store the hash without overflowing
    char *compare = crypt(p, salt);
    strcpy(hash, compare);
    

    or more tersely,

    char hash[256];
    strcpy(hash, crypt(p, salt));
    

    In this way, hash won't be overwritten when crypt(3) is called again.

    Remember to null check the result of crypt(3) before using it as it may return a null pointer on error.

    char *compare = crypt(p, salt);
    compare = crypt(p, salt);
    if (compare) { // null check
        if (strcmp(compare, input) == 0) }
            printf("%s is identical to %s!", compare, input);
        } else {
            printf("%s does not match %s."), compare, input);
        }
    }
    

    Since you are working with c-strings and we know they are null terminated, it's possible to compare them using strcmp(3), if you were with raw bytes, or char arrays not guaranteed to be null terminated, it would be better to use memcmp(3) for comparison.