MD5消息摘要算法(英語:MD5?Message-Digest Algorithm),一種被廣泛使用的密碼散列函數(shù)棋恼,可以產(chǎn)生出一個(gè)128位(16字節(jié))的散列值(hash value)湘纵,用于確保信息傳輸完整一致脂崔。
? ? 這波解釋是不是很正經(jīng)嚴(yán)肅,好像看懂了梧喷,但是如果有人問MD5是什么砌左,MD5就是...就是小編也不知道,通俗一點(diǎn)MD5是一種算法铺敌,用于數(shù)據(jù)的安全方面對(duì)數(shù)據(jù)進(jìn)行加密和解密汇歹,雖然MD5被認(rèn)為不安全,而且漸漸被AES所取代偿凭,但是對(duì)于一般的情況下使用時(shí)可以的产弹,例如某個(gè)管理后臺(tái)的賬號(hào)密碼加密,普通的HTTP請(qǐng)求簽名弯囊,數(shù)據(jù)庫存儲(chǔ)的一些重要數(shù)據(jù)加密痰哨,在這小編就說一下MD5在Java上的使用。
? ? 在JDK內(nèi)部集成多種算法匾嘱,包括MD5和AES等斤斧,那MD5在Java上的使用就非常簡單了,默認(rèn)的加密是小寫的奄毡,如下
????知道你們這些懶人肯定要可以復(fù)制的源碼折欠,小編會(huì)在最后附上整個(gè)工具類的源碼的,默認(rèn)的加密就是生成小寫吼过,但是如果想要使用大寫也非常簡單锐秦,就是使用,自定義一個(gè)數(shù)組盗忱,代碼如下
? ? 下面附上整個(gè)工具類的源碼酱床,小編哪里有寫的不好或者有錯(cuò)誤,希望大家能留言指出
import org.apache.commons.codec.binary.Hex;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
/**
* @date 2019/9/16 10:30
*/
public class MD5Utils {
/**
? ? * 字符串MD5(小寫+字母)
*
? ? * @param str 要進(jìn)行MD5的字符串
? ? */
? ? public static StringgetStrMD5(String str) {
// 獲取MD5實(shí)例
? ? ? ? MessageDigest md5 =null;
? ? ? ? try {
md5 = MessageDigest.getInstance("MD5");
? ? ? ? }catch (NoSuchAlgorithmException e) {
e.printStackTrace();
? ? ? ? ? ? System.out.println(e.toString());
? ? ? ? ? ? return "獲取MD5實(shí)例異常";
? ? ? ? }
// 將加密字符串轉(zhuǎn)換為字符數(shù)組
? ? ? ? char[] charArray = str.toCharArray();
? ? ? ? byte[] byteArray =new byte[charArray.length];
? ? ? ? // 開始加密
? ? ? ? for (int i =0; i < charArray.length; i++)
byteArray[i] = (byte) charArray[i];
? ? ? ? byte[] digest = md5.digest(byteArray);
? ? ? ? StringBuilder sb =new StringBuilder();
? ? ? ? for (int i =0; i < digest.length; i++) {
int var = digest[i] &0xff;
? ? ? ? ? ? if (var <16)
sb.append("0");
? ? ? ? ? ? sb.append(Integer.toHexString(var));
? ? ? ? }
return sb.toString();
? ? }
/**
? ? * 字符串MD5(大寫+字母)
*
? ? * @param password 要進(jìn)行MD5的字符串
? ? */
? ? public static StringgetStrrMD5(String password) {
char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
? ? ? ? try {
byte strTemp[] = password.getBytes("UTF-8");
? ? ? ? ? ? MessageDigest mdTemp = MessageDigest.getInstance("MD5");
? ? ? ? ? ? mdTemp.update(strTemp);
? ? ? ? ? ? byte md[] = mdTemp.digest();
? ? ? ? ? ? int j = md.length;
? ? ? ? ? ? char str[] =new char[j *2];
? ? ? ? ? ? int k =0;
? ? ? ? ? ? for (int i =0; i < j; i++) {
byte byte0 = md[i];
? ? ? ? ? ? ? ? str[k++] = hexDigits[byte0 >>>4 &15];
? ? ? ? ? ? ? ? str[k++] = hexDigits[byte0 &15];
? ? ? ? ? ? }
return new String(str);
? ? ? ? }catch (Exception e) {
return null;
? ? ? ? }
}
/**
? ? * 加鹽MD5
*/
? ? public static StringgetSaltMD5(String password) {
// 生成一個(gè)16位的隨機(jī)數(shù)
? ? ? ? Random random =new Random();
? ? ? ? StringBuilder sBuilder =new StringBuilder(16);
? ? ? ? sBuilder.append(random.nextInt(99999999)).append(random.nextInt(99999999));
? ? ? ? int len = sBuilder.length();
? ? ? ? if (len <16) {
for (int i =0; i <16 - len; i++) {
sBuilder.append("0");
? ? ? ? ? ? }
}
// 生成最終的加密鹽
? ? ? ? String Salt = sBuilder.toString();
? ? ? ? password =md5Hex(password + Salt);
? ? ? ? char[] cs =new char[48];
? ? ? ? for (int i =0; i <48; i +=3) {
cs[i] = password.charAt(i /3 *2);
? ? ? ? ? ? char c = Salt.charAt(i /3);
? ? ? ? ? ? cs[i +1] = c;
? ? ? ? ? ? cs[i +2] = password.charAt(i /3 *2 +1);
? ? ? ? }
return String.valueOf(cs);
? ? }
/**
? ? * 驗(yàn)證加鹽后是否和原文一致
? ? * @param password? md5原文
? ? * @param md5str? ? 加鹽md5后的md5串
? ? */
? ? public static boolean getSaltverifyMD5(String password, String md5str) {
char[] cs1 =new char[32];
? ? ? ? char[] cs2 =new char[16];
? ? ? ? for (int i =0; i <48; i +=3) {
cs1[i /3 *2] = md5str.charAt(i);
? ? ? ? ? ? cs1[i /3 *2 +1] = md5str.charAt(i +2);
? ? ? ? ? ? cs2[i /3] = md5str.charAt(i +1);
? ? ? ? }
String Salt =new String(cs2);
? ? ? ? return md5Hex(password + Salt).equals(String.valueOf(cs1));
? ? }
/**
? ? * 單次加密趟佃,雙次解密
? ? */
? ? public static StringgetconvertMD5(String inStr) {
char[] charArray = inStr.toCharArray();
? ? ? ? for (int i =0; i < charArray.length; i++) {
charArray[i] = (char) (charArray[i] ^'t');
? ? ? ? }
String str = String.valueOf(charArray);
? ? ? ? return str;
? ? }
/**
? ? * 使用Apache的Hex類實(shí)現(xiàn)Hex(16進(jìn)制字符串和)和字節(jié)數(shù)組的互轉(zhuǎn)
? ? */
? ? @SuppressWarnings("unused")
private static Stringmd5Hex(String str) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
? ? ? ? ? ? byte[] digest = md.digest(str.getBytes());
? ? ? ? ? ? return new String(new Hex().encode(digest));
? ? ? ? }catch (Exception e) {
e.printStackTrace();
? ? ? ? ? ? System.out.println(e.toString());
? ? ? ? ? ? return "";
? ? ? ? }
}
public static void main(String[] args) {
System.out.println(getSaltMD5("admin"));
? ? ? ? System.out.println(getSaltverifyMD5("admin","092956b6b61a40a011f3076c650194991954f3584fa92220"));
? ? ? ? System.out.println(getconvertMD5("admin"));
? ? ? ? System.out.println(getconvertMD5(getconvertMD5("admin")));
? ? }
}
補(bǔ)充說明:
MD5加密算法為現(xiàn)在應(yīng)用最廣泛的哈希算法之一扇谣,該算法廣泛應(yīng)用于互聯(lián)網(wǎng)網(wǎng)站的用戶文件加密,能夠?qū)⒂脩裘艽a加密為128位的長整數(shù)闲昭。數(shù)據(jù)庫并不明文存儲(chǔ)用戶密碼罐寨,而是在用戶登錄時(shí)將輸入密碼字符串進(jìn)行MD5加密,與數(shù)據(jù)庫中所存儲(chǔ)的MD5值匹配序矩,從而降低密碼數(shù)據(jù)庫被盜取后用戶損失的風(fēng)險(xiǎn)鸯绿。
MD5加密算法以512位分組來處理輸入的信息,且每一分組又被劃分為16個(gè)32位子分組,經(jīng)過了一系列的處理后瓶蝴,算法的輸出由四個(gè)32位分組組成毒返,將這四個(gè)32位分組級(jí)聯(lián)后將生成一個(gè)128位散列值。