Md5用盐编码

时间:2012-02-09 04:56:06

标签: spring authentication md5 salt

我正在将基于joomla的cms系统的一些数据迁移到基于Spring的Java EE环境。

在分析过程中我发现密码的md5实现与joomla不一样???任何想法为什么md5实现差异?

例如: 如果joomla记录有一个密码字段,如“3c57ebfec712312f30c3fd1981979f58:WnvTroeiBmd5bjGmmsVUnNjppadH7giK”(这里3c57ebfec712312f30c3fd1981979f58是最终的md5哈希摘要,WnvTroeiBmd5bjGmmsVUnNjppadH7giK是附加用户密码输入的关键字),当用户尝试登录时在弹簧系统中这个记录失败了。

在基于Spring的Java EE系统中,我们使用哈希编码器作为md5,将盐用作某个变量,WnvTroeiBmd5bjGmmsVUnNjppadH7giK在这里。

Junit Code代码段:此测试用例失败。

@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 个答案:

答案 0 :(得分:2)

以上不起作用(包括挑战评论)。以下代码来自此处 - http://forum.joomla.org/viewtopic.php?t=207689#p993378并确认适用于盐渍和非盐渍密码。

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();      
   }
}

答案 1 :(得分:0)

Spring的Md5PasswordEncoder从未声称与Joomla的盐渍MD5密码兼容。

简而言之,它无法运作。你需要Java代码做与Joomla相同的事情。

http://forum.joomla.org/viewtopic.php?t=207689#p993378声称是这样一段代码,你应该尝试一下。

如果它不起作用,最可能的罪魁祸首可能是编码问题,你必须确保将Java字符串(16位宽字符)转换为PHP兼容的字节表示。

此外,您应该考虑迁移路径,以实现更强大的密码派生功能,例如PBKDF2