0

I was testing the crypt function, and stumbled on this part which I could not understand:

  • If I simply load the salt (50) and the key (rofl), and use crypt to hash the key, it works out fine.
  • But then I tried using crypt 1 more time, this time passing in the hash (50fkUxYHbnXGw) and using the key (rofl) as the salt. Now the 2 results are identical. strcmp() indicated that they are the same. But they cannot be. Not only that, but both crypt functions now return a hash that is different from what the hash of "rofl" should be. See the code below. The printf function would return "roMoPGr3r5IJg roMoPGr3r5IJg" and now this is stumping me.

The initial reason for trying this was because I was trying to use crypt to hash 2 different keys using the same salt (50) and the result are identical as well. For instance, I would use 2 keys such as "abc" and "12" and crypt(key1, salt) and crypt(key2, salt) would return identical results. Does someone understand this?

#define _XOPEN_SOURCE
#include <unistd.h>
#include <string.h>
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>

int main (void)
{
string salt = "50";
string key = "rofl";
string hash = "50fkUxYHbnXGw";
string code1 = crypt(key,salt);
string code2 = crypt(hash,key);
printf("%s %s \n",code1,code2);
if (strcmp(code1, code2) == 0)
    printf("Hm they are equal\n");
return 0;
}
2

From the man page for crypt: (under Description)

The return value points to static data whose content is overwritten by each call.

This means that each time you call crypt it encrypts the key using salt and stores the result in a specific (static) memory location. The return value is actually a pointer to that value, not the value itself. In the lectures on pointers you'll find that string is just a char* which is a pointer to a "string", not a string itself.

When you make the second call to crypt it does the same thing, using the exact same result location in memory. The return value is another pointer, to the SAME static memory location. Both code1 and code2 point to the same exact location, which is the result from the second function call.

You can test this with the following:

char* salt = "50";
char* pass1 = "abcdefg";
char* pass2 = "password";

char* hash1 = crypt(pass1, salt);
printf("%10s: %s\n", pass1, hash1);

char* hash2 = crypt(pass2, salt);
printf("%10s: %s\n", pass2, hash2);

printf("%10s: %s\n", pass1, hash1);

The results:

   abcdefg: 50ozejrWnaK1U
  password: 50q.zrL5e0Sak
   abcdefg: 50q.zrL5e0Sak

NOW you will see different results for the keys. This is because I'm printing the first value hash1 BEFORE calling crypt the second time. But if I try to print out hash1 again after the second call, the string has been overwritten.

There are a couple options for using crypt multiple times. Either use the value in a comparison right after you call it (before another function call). Or use strcpy/strncpy to copy the string into your own local variable:

char* salt = "50";
char* pass1 = "abcdefg";
char* pass2 = "password";

char* hash1 = crypt(pass1, salt);
char str1[14];  // 13 chars + \0
strncpy(str1, hash1, 13);
str1[13] = '\0';

char* hash2 = crypt(pass2, salt);
char str2[14];
strncpy(str2, hash2, 13);
str2[13] = '\0';

printf("%10s: %s\n", pass1, str1);
printf("%10s: %s\n", pass2, str2);

Now you have an actual copy of the hash stored in memory for you to use.

1
  • Thanks, that answers it. I was not careful enough to look at the return description closely! I was able to do crack anyway, but it's always good to dig around a bit – buitri84 Sep 11 '17 at 15:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .