/* This string is magic for this algorithm. Having it this way,
* we can get get better later on */
String magic = "$1$";
byte finalState[];
MessageDigest ctx, ctx1;
long l;
/* -- */
/* Refine the Salt first */
/* If it starts with the magic string, then skip that */
if (salt.startsWith(magic))
{
salt = salt.substring(magic.length());
}
/* It stops at the first '$', max 8 chars */
if (salt.indexOf('$') != -1)
{
salt = salt.substring(0, salt.indexOf('$'));
}
if (salt.length() > 8)
{
salt = salt.substring(0, 8);
}
ctx = MessageDigest.getInstance("MD5");
ctx.update(password.getBytes()); // The password first, since that is what is most unknown
ctx.update(magic.getBytes()); // Then our magic string
ctx.update(salt.getBytes()); // Then the raw salt
/* Then just as many characters of the MD5(pw,salt,pw) */
ctx1 = MessageDigest.getInstance("MD5");
ctx1.update(password.getBytes());
ctx1.update(salt.getBytes());
ctx1.update(password.getBytes());
finalState = ctx1.digest();
for (int pl = password.length(); pl > 0; pl -= 16)
{
for( int i=0; i< (pl > 16 ? 16 : pl); i++ )
ctx.update(finalState[i] );
}
/* the original code claimed that finalState was being cleared
to keep dangerous bits out of memory, but doing this is also
required in order to get the right output. */
clearbits(finalState);
/* Then something really weird... */
for (int i = password.length(); i != 0; i >>>=1)
{
if ((i & 1) != 0)
{
ctx.update(finalState[0]);
}
else
{
ctx.update(password.getBytes()[0]);
}
}
finalState = ctx.digest();
/*
* and now, just to make sure things don't run too fast
* On a 60 Mhz Pentium this takes 34 msec, so you would
* need 30 seconds to build a 1000 entry dictionary...