一個密碼經過多次MD5加密能否提高安全性?Java MD5鹽值加解密


 

什么是MD5?

MD5(Message Digest Algorithm 5,信息摘要算法5),是計算機廣泛使用的摘要算法(又稱哈希算法)之一。MD5是將一段信息,通過其不可逆的字符串變換算法,產生了唯一的MD5信息摘要(16位或32位固定長度的字符串)。即同一明文一定生成固定的密文。

為了防止用戶登錄密碼泄露,數據庫存儲的密碼不能是明文,即使數據庫泄露了密碼也不能直接泄露。通常的做法是將用戶設置的登錄密碼進行MD5運算/加密后存入數據庫。

當用戶登錄時,對用戶輸入的密碼進行MD5運算,運算結果與數據庫中的值進行比對,如果MD5密文一樣,則認為用戶登錄密碼正確,反之則認為密碼錯誤。

以上是MD5最為普遍的使用方式

講個小故事:

前段時間全國2600多只隊伍、一萬多人參加的網絡安全比賽(各方大佬開心虐菜)。有一道賽題就是關於md5的web題,那道題一共三關,每一關都考驗了md5值相等或者相同,最后一關是md5全等,聽說需要md5碰撞產生兩個相同的數值,而如果你想從一個md5值恢復到原來的值是非常困難的。

MD5加密是什么?

MD5加密使用的是hash算法,一種被廣泛使用的密碼散列函數,可以產生出一個128位(16字節)的散列值(hash value),也就是一共有2^128種可能,大概是3.4*10^38,這個數字是有限多個的,而但是世界上可以被用來加密的原文則會有無數的可能性。

2009年,中國科學院的謝濤和馮登國僅用了220.96的碰撞算法復雜度,破解了MD5的碰撞抵抗,該攻擊在普通計算機上運行只需要數秒鍾。我使用過md5碰撞生成器,可以生成兩個md5值相同但是內容不同的文件。

md5解密網站的原理

相信你在網上可以找到很多破解md5的網站,為什么能破解呢?是因為這些站點中存儲了md5加密數據,通過查找數據庫中對應的md5密文找到相對應的加密數據。

一個MD5密文理論上可能對應多個原文,通過遍歷法可以暴力破解密碼,但這是計算時間、計算資源的巨大消耗。

多次MD5加密

那么多次MD5加密能否提高密碼的安全性呢?理論上肯定是安全一些,對暴力破解密碼能起到一定的作用吧,畢竟盲破解是不管進行了幾次MD加密的。

目前幾乎所有常用的密碼的一次md5、二次md5甚至3次md5的結果都被計算出來存到一個彩虹表里。當然你加密的次數越多肯定會越安全,不過呢最好的辦法是在每一次md5加密之后你在密文后再加點數據,然后再進行md5加密,這樣就不會被破解了。

下邊介紹一下鹽值加密,什么是鹽值加密呢。就是通過生成隨機數與MD5生成字符串進行組合,這樣的隨機性和不確定性就算是再怎么厲害的站長工具都解不開。 

MD5鹽值(隨機鹽值)加解密流程

MD5鹽值加解密 工具類:

 1 import java.security.MessageDigest;
 2 import java.util.Random;
 3  
 4 import org.apache.commons.codec.binary.Hex;
 5  
 6 /**
 7  * MD5鹽值加解密 工具類
 8  * @author sun
 9  * @date 2018年5月22日 上午11:18:00
10  */
11 public class PasswordUtil {
12     /**
13      * 生成含有隨機鹽的密碼
14      */
15     public static String generate(String password) {
16         Random r = new Random();
17         StringBuilder sb = new StringBuilder(16);
18         sb.append(r.nextInt(99999999)).append(r.nextInt(99999999));
19         int len = sb.length();
20         if (len < 16) {
21             for (int i = 0; i < 16 - len; i++) {
22                 sb.append("0");
23             }
24         }
25         String salt = sb.toString();
26         password = md5Hex(password + salt);
27         char[] cs = new char[48];
28         for (int i = 0; i < 48; i += 3) {
29             cs[i] = password.charAt(i / 3 * 2);
30             char c = salt.charAt(i / 3);
31             cs[i + 1] = c;
32             cs[i + 2] = password.charAt(i / 3 * 2 + 1);
33         }
34         return new String(cs);
35     }
36  
37     /**
38      * 校驗密碼是否正確
39      */
40     public static boolean verify(String password, String md5) {
41         char[] cs1 = new char[32];
42         char[] cs2 = new char[16];
43         for (int i = 0; i < 48; i += 3) {
44             cs1[i / 3 * 2] = md5.charAt(i);
45             cs1[i / 3 * 2 + 1] = md5.charAt(i + 2);
46             cs2[i / 3] = md5.charAt(i + 1);
47         }
48         String salt = new String(cs2);
49         return md5Hex(password + salt).equals(new String(cs1));
50     }
51  
52     /**
53      * 獲取十六進制字符串形式的MD5摘要
54      */
55     public static String md5Hex(String src) {
56         try {
57             MessageDigest md5 = MessageDigest.getInstance("MD5");
58             byte[] bs = md5.digest(src.getBytes());
59             return new String(new Hex().encode(bs));
60         } catch (Exception e) {
61             return null;
62         }
63     }
64  
65     public static void main(String[] args) {
66         String password = generate("111111");
67         System.out.println(password);
68         System.out.println(verify("111111", password));
69     }
70 }

固定鹽值就是將上文中的salt換成固定串值。

總結:首先md5不是加密,其次加鹽防的是彩虹表,加固定鹽效果當然不如隨機鹽,但比沒鹽還是好得多!

git代碼:https://github.com/dingsai88/StudyTest/tree/master/src/com/ding/util/md5

 




 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM