- MD5加密
- 加鹽加密
- 項目密碼升級
MD5加密
MD5一系列公式進行復雜數學運算;特點:(用途校驗和、計算hash值方式、加密)
1:定長;無論原始數據多長;算出的結果都是4或者8字節的版本。
2:沖突概率很小;就算你只改動一個地方;但是計算的結果相比之下是非常大
3:不可逆;正著計算很容易;逆著計算理論不可能實現;計算量很大;當前的條件是不可能實現
彩虹表:網上解密的工具只能把一些常見的字符串MD5值保存好;然后進行查表的值;并不是真實的計算出結果。
java中如何將一段這種字符串的password進行MD5加密呢:
DigestUtils.md5DigestAsHex是Apache Commons Codec庫中的一個工具方法,用于計算傳入參數的MD5哈希值,并返回一個16進制字符串表示的結果。
傳入的參數需要是一個字節數(byte[])或字符串(String)。如果參數是字符串,則會自動將其轉換為對應的字節數組。
String password="12345678";
String md5password=DigestUtils.md5DigestAsHex(password.getBytes());
System.out.println(md5password);
同一個字符串md5的值一個固定值;如果人家獲取到你的md5這個值;破解密碼隨隨便便;直接遍歷彩虹表窮舉;相當于加一把沒帶鑰匙的鎖
加鹽加密
加密:密碼+隨機鹽值 進行md5加密
解密:我們也沒法解;因為是不可逆的;我們記住加密規則;再走一遍流程;對比用戶登錄的密碼和數據庫的是否一樣
鹽值:
我們得知道鹽值是什么;才能重新再走一遍的規則;那就涉及鹽值怎么來的;怎么儲存
獲取鹽值:
String salt=UUID.randomUUID().toString().replace("-","");
//UUID一般被表示為32個字符的十六進制數,最常用的格式是8-4-4-4-12的五段分割
//例如:c4a760a8-dbcf-11e9-8f92-2b1af3aec0a6;我們把橫杠去掉;替換成空字符串
你的鹽值要每次不一樣(每個用戶的是不一樣);那么就使用uuid;時間戳有可能重復。多個人的隨機鹽值是一樣;會造成破解多個和破解一個是一樣難度。
儲存鹽值:
方式1:鹽值和密碼單獨存儲兩個字段(如果對方破解你數據庫內容;那就很危險;相當于我告訴黑客;鹽值是……;你自己去用彩虹表加密遍歷一下和我的這個密碼對比) 不現實
方式2:鹽值和密碼整合一起;存在一個字段。(用一個分隔符;分割哪里是鹽值;哪里是MD5后的密碼;給黑客破解增加難度;它還得猜你哪個是分隔符;那邊是鹽值;哪邊是密碼)
使用一個規則約定這里鹽值和密碼:分隔符(缺點;傳遞的正文不能有這個分隔符)?或者是按位數;前32位存鹽值、后32位存密碼。
為什么加鹽值后破解成本大大提升:
假設我的鹽值是1-n(實際更復雜);要暴力破解對應n個彩虹表;得拿鹽值去和彩虹表的每一個進行MD5再和我們的密碼對比。而且這樣子破解的只是一個用戶。
代碼實現:
package com.example.demo.service;import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;import java.util.UUID;public class salt_encrypt {//加密過程;相當于注冊的時候要用于存進去數據庫的password字段public static String encrypt(String reg_password){String salt= UUID.randomUUID().toString().replace("-","");String md5password= DigestUtils.md5DigestAsHex((reg_password+salt).getBytes());String dbpassword=salt+"$"+md5password;return dbpassword;}public static boolean decrypt(String login_password,String dbpassword){boolean result=false;//判空操作if(StringUtils.hasLength(login_password)&&StringUtils.hasLength(dbpassword)){//取出鹽值String [] dbpassword1=dbpassword.split("\\$");
// 因為 "$" 在正則表達式中具有特殊含義。在正則表達式中,"$" 表示行結束的位置,
// 如果不進行轉義,正則表達式會將它解釋為行結束符意思,而不是普通的字符 "$"。String salt=dbpassword1[0];String dbpassword2=dbpassword1[1];//獲取我們直接用數據庫的鹽值+分隔符+md5密碼是否包含這個要驗證的密碼md5值login_password=DigestUtils.md5DigestAsHex((login_password+salt).getBytes());if(dbpassword1.equals(login_password)){result=true;}}return result;}}
項目密碼升級
代碼改造:
UserController的注冊;修改前
修改后:存的密碼變成加鹽md5后的
UserController的登錄:修改前
修改后:
檢查數據庫password的字段是否是65位的;因為我們之前可能沒使用加鹽加密就沒考慮那么多;如果我們之前隨時password varchar(32)那么可以通過alter table userinfo modify column password varchar(65);進行修改
驗證:
注冊成功;且儲存的密碼樣式是我們需要的。登錄成功;說明驗證是通過了。
Spring 框架提供了有加鹽加密的方式,最常用的是Spring Security :
1:使用先添加Security框架
2:內置一個登錄頁面;我們得把這個關閉掉(因為我們自己有登錄頁面;不需要用它的)
它會在控制臺提供一個密碼給你
如何關閉:
在啟動類添加這個(自動注入;關閉這個類自動的加載;但是APi還是能用的;因為我們把這個依賴加入項目了;;spring是真的默認是自動加載的)
使用: