目錄
MD5加密
MD5加密是一種常見的加密方式,我們經常用在保存用戶密碼和關鍵信息上。那么它到底有什么,又什么好處呢,會被這么廣泛的運用在應用開發中。
什么是MD5
MD5加密全程是Message-Digest Algoorithm 5(信息-摘要算法),它對信息進行摘要采集,再通過一定的位運算,最終獲取加密后的MD5字符串。
例如我們要加密一篇文章,那么我們會隨機從每段話或者每行中獲取一個字,把這些字統計出來后,再通過一定的運算獲得一個固定長度的MD5加密后信息。因此,其很難被逆向破解。
MD5有哪些特點
- 針對不同長度待加密的數據、字符串等等,其都可以返回一個固定長度的MD5加密字符串。(通常32位的16進制字符串);
- 其加密過程幾乎不可逆,除非維護一個龐大的Key-Value數據庫來進行碰撞破解,否則幾乎無法解開。
- 運算簡便,且可實現方式多樣,通過一定的處理方式也可以避免碰撞算法的破解。
- 對於一個固定的字符串。數字等等,MD5加密后的字符串是固定的,也就是說不管MD5加密多少次,都是同樣的結果。
java中實現MD5加密方式
1. 使用JDK自帶的API實現
加單實現如下
@Test
void test1() {
String pwd = "123456";
try {
MessageDigest md = MessageDigest.getInstance("MD5");// 生成一個MD5加密計算摘要
md.update(pwd.getBytes());// 計算md5函數
/**
* digest()最后確定返回md5 hash值,返回值為8位字符串。
* 因為md5 hash值是16位的hex值,實際上就是8位的字符
* BigInteger函數則將8位的字符串轉換成16位hex值,用字符串來表示;得到字符串形式的hash值
* 一個byte是八位二進制,也就是2位十六進制字符(2的8次方等於16的2次方)
*/
String hashedPwd = new BigInteger(1, md.digest()).toString(16);// 16是表示轉換為16進制數
System.out.println(hashedPwd);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
結果:
e10adc3949ba59abbe56e057f20f883e
2. 使用Spring的DigestUtils工具類
@Test
void testMD5() {
String pwd = "123456";
// 基於spring框架中的DigestUtils工具類進行密碼加密
String hashedPwd1 = DigestUtils.md5DigestAsHex((pwd).getBytes());
System.out.println(hashedPwd1);
}
結果:
e10adc3949ba59abbe56e057f20f883e
改進- 加鹽
一般加密算法固定,很容易破解,安全系數低,有很多網站可以直接破解密文。為了提高安全性,可以采取加鹽的方式。生成一組隨機串,保存在數據庫中,然后混雜在原來的密碼中,再通過加密算法加密,存進數據庫中
@Test
void testMD5() {
String pwd = "123456";
String salt = UUID.randomUUID().toString();
// 基於spring框架中的DigestUtils工具類進行密碼加密
String hashedPwd1 = DigestUtils.md5DigestAsHex((pwd + salt).getBytes());
System.out.println(hashedPwd1);
}
結果:
ce504625e463008803c1b875a0bd87a3
改進-加次數
多加密幾次也可增加破解的難度, 一般可用於交易碼等
@Test
void testMD5() {
String pwd = "123456";
String salt = UUID.randomUUID().toString();
// 基於spring框架中的DigestUtils工具類進行密碼加密
String hashedPwd1 = DigestUtils.md5DigestAsHex((pwd + salt).getBytes());
hashedPwd1 = DigestUtils.md5DigestAsHex((hashedPwd1 + salt).getBytes()); // +1次
hashedPwd1 = DigestUtils.md5DigestAsHex((hashedPwd1 + salt).getBytes()); // +2次
// ... 可使用循環等
System.out.println(hashedPwd1);
}
結果:
22cca33f84e7c72132dbff6fcfc60934
3. 使用Shiro的simpleHash進行加密
當然, 我們也可以加鹽加次數等
如下代碼
@Test
void testShiroMD5() {
String pwd = "123456"; // 密碼
String salt = UUID.randomUUID().toString(); // 鹽
/**
* 參數1: 加密方式
* 參數2: 要加密的字符串
* 參數3: 鹽
* 參數4: 加密次數
*/
SimpleHash sh = new SimpleHash("MD5", pwd, salt, 5); // 定義simpleHash對象
String hashedPwd = sh.toHex(); // 生成16進制密文
System.out.println(hashedPwd); // 輸出
}
結果
b37e9129e9a6c1cecc8d34c60315fd8d