Saturday, January 08, 2011

UnixCrypt produces same values for different passwords

This is interesting. Learnt something new today.

I've been using the UnixCrypt class from Jetty and if the first eight characters of the password to be encrypted are the same for two passwords, the resulting encrypted (hashed) value is the same.

I was trying to reproduce an error message in my program by providing the wrong password and creating the wrong password by simply modifying the last character of the password. However, inspite of supplying the wrong password, the system was successfully authenticating.

The problem was that two different passwords like John1234$ and John1234b#, were producing the same value from UnixCrypt which was leading the system to think that it was the correct password. BTW, notice that one could potentially call these passwords quite strong given they have an Uppercase, lowercase, numbers, a special character and are greater than 8 characters.

The only way to get different values is to use completely different salts. But even there is a catch. Salts like '12abc$1' and '12gfd#2345' though completely different, produce the same value.

I've been using the class as part of a program that saves passwords and was using a salt of format - "constant + random". This was resulting in same value even though the salt was technically different. Here is a test program and the resulting output - (some boilerplate code omitted for brevity)

Code

String password = "John1234$";

String salt = "12abc$1";

String val = UnixCrypt.crypt(password,salt);

System.out.println("(" + password + "," + salt + ")" + " = " + val);

password = "John1234b#";

salt = "12gfd#2345";

val = UnixCrypt.crypt(password, salt);

System.out.println("(" + password + "," + salt + ")" + " = " + val);


Output

(John1234$,12abc$1) = 12FH7.yEd/XWI

(John1234b#,12gfd#2345) = 12FH7.yEd/XWI


Why is this happening even when the salts are completely different? The problem is again the prefix. Looks like if the first two characters of the salt are same, the same value is produced. Simply altering the second character of the salts, '12abc$1' and '13gfd#2345' , results in different values.

New Output with second character of the salt changed -

(John1234$,12abc$1) = 12FH7.yEd/XWI

(John1234b#,13gfd#2345) = 13uN.eBnCs5io



Ideally, the salts should be dynamically generated. However, even if that is done, likelihood of a collision is quite high due to the small size of the salt prefix.

At this point the only certain way around that I can think of is to ensure that two passwords don't have the same first 8 characters.

When I get time it will be good to look into why this is happening. A little bit of browsing around the web told me that this might have something to do with the MD5 hashing algo but that is an exploration for another day.

2 comments:

Unknown said...

Yes, this is how crypt works for passwords. It is also the reason that most Linux distress have been moving away from using crypt for passwords.

Aashish Patil said...

Thanks Petri, that makes sense.

  DB Reading BASE: An Acid Alternative: In partitioned databases, trading some consistency for availability can lead to dramatic improvement...