2012-02-09 57 views
1

我正在將一些數據從基於joomla的cms系統遷移到基於spring的Java EE環境。Md5與鹽編碼

在分析過程中我發現密碼的md5實現和joomla不一樣?任何想法爲什麼在md5實現差異?

例如: 如果的Joomla記錄有一個密碼字段,如「3c57ebfec712312f30c3fd1981979f58:WnvTroeiBmd5bjGmmsVUnNjppadH7giK」(這裏3c57ebfec712312f30c3fd1981979f58是最終MD5散列摘要和WnvTroeiBmd5bjGmmsVUnNjppadH7giK是鍵與用戶輸入的密碼被附加),並且當用戶嘗試與該記錄中登錄彈簧系統失敗。

在基於spring的Java EE系統中,我們使用散列編碼器作爲md5,salt作爲一些變量,這裏是WnvTroeiBmd5bjGmmsVUnNjppadH7giK

Junit代碼片段:該測試用例失敗。

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

} 

回答

0

Spring的Md5PasswordEncoder從來沒有聲稱要與Joomla的醃MD5口令兼容。

總之,它不能工作。您需要Java代碼執行與Joomla相同的操作。

http://forum.joomla.org/viewtopic.php?t=207689#p993378聲稱是這樣一段代碼,你應該試一下。

如果它不起作用,可能是編碼問題,您必須確保將Java字符串(16位寬字符)轉換爲PHP兼容的字節表示形式。

另外,您應該考慮朝向更強密碼派生函數(如PBKDF2)的遷移路徑。

+0

我花了近一天來解決this.Below測試用例工作@Test 公共無效testSpringMD5Functionality(){ 字符串md5MigratedPassword = 「3c57ebfec712312f30c3fd1981979f58:WnvTroeiBmd5bjGmmsVUnNjppadH7giK」; String [] m = md5MigratedPassword.split(「:」); Md5PasswordEncoder passwordEncoder = new Md5PasswordEncoder(); passwordEncoder.setEncodeHashAsBase64(false); 布爾值= passwordEncoder.isPasswordValid(m [0] + m [1],「password」,null); assertTrue(value); //測試用例通過 } – challenge 2012-02-11 05:29:07

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