1
votes

I am migrating some data from joomla based cms system to spring based Java EE environment .

During analysis I found that md5 implementation of passwords is not same as joomla ??? Any idea why difference in md5 implementation ??

For example : if joomla record had a password field like "3c57ebfec712312f30c3fd1981979f58:WnvTroeiBmd5bjGmmsVUnNjppadH7giK" (here 3c57ebfec712312f30c3fd1981979f58 is final md5 hash digest and WnvTroeiBmd5bjGmmsVUnNjppadH7giK is key to be appended with user password input) and when the user tries to login with this record in spring system it fails.

In spring based Java EE system , we use hash encoder as md5 and salt as some variable which is WnvTroeiBmd5bjGmmsVUnNjppadH7giK here.

Junit Code snippet: This test case fails.

@Test
public void testSpringMD5Functionality() {

    String md5MigratedPassword = "3c57ebfec712312f30c3fd1981979f58:WnvTroeiBmd5bjGmmsVUnNjppadH7giK";
    String[] m = md5MigratedPassword.split(":");

    Md5PasswordEncoder passwordEncoder = new Md5PasswordEncoder();
    passwordEncoder.setEncodeHashAsBase64(false);
    boolean value = passwordEncoder.isPasswordValid(m[0], "password", m[1]);
    assertTrue(value); //test case fails ?????

}
2

2 Answers

2
votes

The above does not work (including comment by challenge). The following code is taken from here - http://forum.joomla.org/viewtopic.php?t=207689#p993378 and confirmed to be working for both salted and non-salted passwords.

public class Joomla15PasswordHash 
{
   public static boolean check(String passwd,String dbEntry) {
      if (passwd==null || dbEntry==null || dbEntry.length()==0)
    throw new IllegalArgumentException();
      String[] arr = dbEntry.split(":",2);
      if (arr.length==2) {
    // new format as {HASH}:{SALT}
    String cryptpass = arr[0];
    String salt = arr[1];

    return md5(passwd+salt).equals(cryptpass);
      } else {
         // old format as {HASH} just like PHPbb and many other apps
    String cryptpass = dbEntry;

    return md5(passwd).equals(cryptpass); 
      }
   }

   static Random _rnd;

   public static String create(String passwd) {
      StringBuffer saltBuf = new StringBuffer();
      synchronized (Joomla15PasswordHash.class) {
    if (_rnd==null) _rnd=new SecureRandom();
    int i;
    for (i=0;i<32;i++) {
       saltBuf.append(Integer.toString(_rnd.nextInt(36),36));
    }
      }
      String salt = saltBuf.toString();

      return md5(passwd+salt)+":"+salt;
   }

   /** Takes the MD5 hash of a sequence of ASCII or LATIN1 characters,
    *  and returns it as a 32-character lowercase hex string.
    *
    *  Equivalent to MySQL's MD5() function 
    *  and to perl's Digest::MD5::md5_hex(),
    *  and to PHP's md5().
    *
    *  Does no error-checking of the input,  but only uses the low 8 bits
    *  from each input character.
    */
   private static String md5(String data) {
      byte[] bdata = new byte[data.length()]; int i; byte[] hash;

      for (i=0;i<data.length();i++) bdata[i]=(byte)(data.charAt(i)&0xff );

      try {
         MessageDigest md5er = MessageDigest.getInstance("MD5");
         hash = md5er.digest(bdata);
      } catch (GeneralSecurityException e) { throw new RuntimeException(e); }

      StringBuffer r = new StringBuffer(32);
      for (i=0;i<hash.length;i++) {
         String x = Integer.toHexString(hash[i]&0xff);
         if (x.length()<2) r.append("0");
         r.append(x);
      }
      return r.toString();      
   }
}
0
votes

Spring's Md5PasswordEncoder never claimed to be compatible with Joomla's salted MD5 passwords.

In short, it can't work. You need Java code doing the same thing than Joomla's does.

http://forum.joomla.org/viewtopic.php?t=207689#p993378 claims to be such a piece of code, you should try it.

If it doesn't work the likest culprit is likely an encoding issue, you must make sure to convert Java string (16 bit wide chars) to a PHP compatible byte representation.

Also you should likely consider a migration path toward a stronger password derivation function such as PBKDF2.