基於鹽+Sha演算法的安全密碼保護機制

餘二五發表於2017-11-07

  密碼通過加鹽後,可以增加密碼的複雜度,即便最簡單的密碼,在加鹽後,也能變成複雜的字串,這大大提高了密碼破解的難度。但是如果將鹽硬編碼在程式中或隨機一次生成的,每個密碼進行hash使用相同的鹽會降低系統的防禦力,因為相同密碼的hash兩次後的結果也是一樣的。所以比較正確的做法是每次建立使用者或修改密碼都使用一個新的隨機鹽


  很多使用者可能想到了將使用者名稱作為鹽的方案,雖然對於每一個使用者來說使用者名稱可能是不同的,但是使用者名稱是可預測的,並不是完全隨機的。攻擊者完全可以用常見的使用者名稱作為鹽來製作查詢表和彩虹表破解hash。


  我們通常使用密碼學上可靠安全的偽隨機數生成器(Cryptographically Secure Pseudo-Random Number Generator (CSPRNG))來生成鹽。正如它的名字說明的那樣,CSPRNG提供一個高標準的隨機數,是完全無法預測的。在Java中,可以使用java.security.SecureRandom生成。


  此外,在web應用中,我們要在服務端進行Hash,而不是客戶端。因為如果Hash在客戶端的話,即便傳輸的不是明文,如果惡意的黑客獲取了使用者的Hash,就可以直接登入帳號了。甚至都不需要知道客戶的明文密碼,也就不需要破解Hash了。我們需要記得客戶端Hash並不是HTTPS的替代品

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
     * 獲取隨機鹽
     * @return
     */
    public static String getSalt(){
        SecureRandom sr;
        byte[] salt = new byte[16];
        try {
          sr = SecureRandom.getInstance("SHA1PRNG""SUN");
          sr.nextBytes(salt);
        catch (Exception e) {
          e.printStackTrace();
        
         
        return salt.toString();
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
     * sha2 加鹽加密
     * @param encryptStr 需要加密的字串
     * @param salt 鹽
     * @return
     */
    public static String sha2EncryptSalt(String encryptStr, String salt){
        MessageDigest md = null;
        String encryptCode = null;
 
        byte[] bt = (encryptStr + salt).getBytes();
        try {
            md = MessageDigest.getInstance("SHA-256");
            md.update(bt);
            encryptCode = bytes2Hex(md.digest()); 
        catch (NoSuchAlgorithmException e) {
            return null;
        }
        return encryptCode;
    }
本文轉自 genuinecx 51CTO部落格,原文連結:http://blog.51cto.com/favccxx/1738655,如需轉載請自行聯絡原作者


相關文章