Subject: Re: crypt(3)
To: None <current-users@netbsd.org>
From: der Mouse <mouse@Collatz.McRCIM.McGill.EDU>
List: current-users
Date: 11/15/1994 10:23:18
>>> [W]ould anyone be interested in a one-way function for passwords
>>> that I built on top of md5?
>> Do it.  Exportability would not be the only plus with using md5.
> Replacing crypt(3) with MD5, if done properly (i.e., a salt was still
> there, arbitrary length passwords were now permitted) would be a
> great boon for everyone, not just those overseas.

I have seen some three or four positive comments and no negative ones
at all.  Here's the algorithm I was using in the other setup where I
have been using md5 to hash passwords.  The reason I'm quoting it here
is that it is likely that crypt(3) is being used in ways I'm not aware
of, and I don't know whether the change in paradigm this would involve
will break anything.  In particular, what I describe below does not
permit the caller to select a salt; does this matter?  hash_password
could, obviously, take an arbitrary-length salt buffer as an argument,
leaving it up to the caller to supply one.

The conversion from binary to base 94 would probably have to be changed
for this to be a drop-in crypt(3) replacement, probably to use a
base-64 conversion similar to that used now; the salt buffer should
probably use getpid() and getppid() instead of random().

hash_password (input: cleartext password, output: hashed password)
	fill a buffer with salt-type data.  I currently use the time of
	  day (the whole struct timeval, including usec) and a call to
	  random(), which makes sense in the context this is being used.
	initialize md5
	feed the salt buffer to md5
	express the 16-byte md5 output as 20 bytes in base 94;
	  call the resulting string the salt string
	initialize DATA to the cleartext password
	repeat ROUNDS times (ROUNDS is a compile-time value, currently 64)
		initialize md5
		feed DATA to md5
		feed the salt string to md5
		feed DATA to md5
		feed the cleartext password to md5
		feed DATA to md5
		take the md5 result and express it in base 94; set DATA
		  to the resulting string
	hashed password is ROUNDS (in cleartext decimal, followed by a
	  terminating dot) concatenated with the 20-byte salt string
	  and the 20-byte final value of DATA (a little over 40 bytes).

check_password (input: cleartext password and stored hashed password,
		output: boolean indicating password correctness)
	initialize DATA to the cleartext password
	extract ROUNDS value from the hashed password; if it is out of
	  range (currently, 1..10240), or the string is otherwise
	  invalid (eg, wrong length), return "password incorrect".
	extract salt string from the hashed password
	initialize DATA to the cleartext password
	repeat ROUNDS times
		initialize md5
		feed DATA to md5
		feed the salt string to md5
		feed DATA to md5
		feed the cleartext password to md5
		feed DATA to md5
		take the md5 result and express it in base 94; set DATA
		  to the resulting string
	if the final value of DATA matches the rest of the hashed
	  password, return "password correct"; otherwise, "password
	  incorrect".

					der Mouse

			    mouse@collatz.mcrcim.mcgill.edu