-1

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!

Roznoshchik
  • 95
  • 1
  • 9
  • 3
    If you share the code you've written, it will be easier to help you. – Cinder Biscuits Jan 04 '19 at 13:47
  • @CinderBiscuits I know. My dilemma here is that I don't want to incorrectly influence any other cs50x student who is looking for solutions. So I thought I could try to generalize first. – Roznoshchik Jan 04 '19 at 13:50
  • It's admiral you don't want to unfairly affect your fellow students, but until you show us what code you've already written, you're unlikely to get an answer to your question – Chris Turner Jan 04 '19 at 14:04
  • String literals have a static storage duration, they exist for the lifetime of the program. You can't update or even write a string literal during runtime. The `crypt(3)` function returns a pointer to the generated password. This password is stored in a static segment of data, but it is not a string literal, and it is overwritten with every call to `crypt(3)`. You can just assign a pointer to the `crypt(3)` result and reassign it every time you call `crypt(3)` if you don't want to do that, you can copy the result using `strcpy(3)` to a `char` array and use the `char` array. – Cinder Biscuits Jan 04 '19 at 14:06
  • Thanks @CinderBiscuits - how do I assign a pointer to the crypt(3) results? and can I compare that pointer to argv[1]? Or would I need to also make a pointer for argv[1] to compare the both of them for equality? I've spent some time reading up on pointers today, but I'm having a hard time understanding how to set the pointer to the value of the function. Because as far as I understand crypt(3) already returns a pointer to the result. – Roznoshchik Jan 04 '19 at 14:10
  • `char *result = crypt(key, salt);` – Cinder Biscuits Jan 04 '19 at 14:12
  • A pointer can be assigned to a pointer. They will both return the same address. Yes, I would suggest that you also create a pointer to `argv[1]`, it will make your code easier to understand. Make sure to null check both as well (`crypt(3)` will return a null pointer if it fails, and `argv[1]` may not exist) – Cinder Biscuits Jan 04 '19 at 14:15
  • What am I doing wrong? @CinderBiscuits `char p[] = "A"; char salt[3]; salt[0] = s[0]; salt[1] = s[1]; char *compare = crypt(p, salt); p[0] = 66; *compare = crypt(p, salt); ` crack.c:28:14: error: incompatible pointer to integer conversion assigning to 'char' from 'char *'; dereference with * [-Werror,-Wint-conversion] *compare = crypt(p, salt); – Roznoshchik Jan 04 '19 at 14:17
  • You don't dereference the pointer to reassign it. `compare = crypt(p, salt);` – Cinder Biscuits Jan 04 '19 at 14:22
  • @CinderBiscuits Thank you so much! that worked. I'm not entirely clear on the details, but I can atleast move forward with the hwk assignment. To get a better understanding of what I was doing wrong, what would you recommend I read up on? I appreciate the help! – Roznoshchik Jan 04 '19 at 14:29
  • I would suggest reading up on pointers and memory allocation. https://pebble.gitbooks.io/learning-c-with-pebble/content/chapter08.html – Cinder Biscuits Jan 04 '19 at 14:34
  • @CinderBiscuits thanks I'll give it a read. Really quickly though - I ran into another issue. `char *p = "A"; p[0] = 65;` gives me a segmentation fault. Why can't I do that? P is the variable I am using to store the autogenerated password. So it will cycle through the alphabet. – Roznoshchik Jan 04 '19 at 15:26
  • `char *p = "A";` Is a pointer to a string literal. String literals are stored statically in a read only part of the program so they cannot be reassigned. `p[0] = 65;` is an attempt to write to that read only address. You either allocate writable storage space for your pointer to point to (a pointer is a reference to a memory address, after all.) This can be done using `malloc(3)` and similar to store in heap, or automatically allocated on the stack with the form `char p[6]`, `6` being the length of the string (including null terminator). – Cinder Biscuits Jan 04 '19 at 15:34
  • In either case, you will not assign a string literal to them directly using `=` you will need to use a function like `strcpy(3)` to copy the characters from the string literal into the char array. – Cinder Biscuits Jan 04 '19 at 15:35

1 Answers1

1

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.

Cinder Biscuits
  • 4,880
  • 31
  • 51