【问题标题】:Md5 with salt encoding带盐编码的 Md5
【发布时间】:2012-03-01 14:45:51
【问题描述】:

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

在分析过程中,我发现密码的 md5 实现与 joomla 不同???知道为什么 md5 实现的不同吗??

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

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

Junit Code sn-p:此测试用例失败。

@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 ?????

}

【问题讨论】:

    标签: spring authentication md5 salt


    【解决方案1】:

    上述方法不起作用(包括挑战评论)。以下代码取自这里 - 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();      
       }
    }
    

    【讨论】:

      【解决方案2】:

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

      简而言之,它行不通。您需要 Java 代码做与 Joomla 相同的事情。

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

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

      此外,您可能应该考虑向更强大的密码派生函数(例如 PBKDF2)迁移路径。

      【讨论】:

      • 我花了将近一天的时间来解决这个问题。下面的测试用例有效 @Test public void testSpringMD5Functionality() { String md5MigratedPassword = "3c57ebfec712312f30c3fd1981979f58:WnvTroeiBmd5bjGmmsVUnNjppadH7giK"; String[] m = md5MigratedPassword.split(":"); Md5PasswordEncoder passwordEncoder = new Md5PasswordEncoder(); passwordEncoder.setEncodeHashAsBase64(false);布尔值 = passwordEncoder.isPasswordValid(m[0]+m[1], "password",null);断言真(值); //测试用例通过 }
      猜你喜欢
      • 1970-01-01
      • 2014-05-03
      • 2010-11-30
      • 2015-06-19
      • 1970-01-01
      • 2016-11-03
      • 2010-09-25
      • 2011-10-27
      • 2016-04-06
      相关资源
      最近更新 更多