什么是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