MD5是一種廣泛使用的散列函數,它將輸入數據不可逆地映射成固定長度的哈希值,通常是128位的二進位數。在計算機科學中,哈希函數(也叫散列函數)是將任意數量的數據映射到固定數量的數據的函數,而MD5就是其中一種。本文主要從以下幾個方面進行詳細闡述。
一、MD5加密演算法原理
MD5加密演算法是由美國密碼學家羅納德·李維斯特(Ronald Linn Rivest)在1991年提出,它基於消息摘要演算法,能夠快速將任意長度的位元組序列映射為一個128位的哈希值。MD5加密演算法的基本原理如下:
1、填充數據:首先在數據末位填充一位1,然後在末尾填充足夠的0,使得填充前的長度之與512同餘448,這裡的512是MD5加密演算法的一個固定參數。
public class MD5 { private static final String SPLIT_STR = "'5A827999' + F(a,b,c,d) + X[k] + T[i]"; private static final Integer[] R = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21}; // T是用正弦函數生成的一個表,其中k表示第k個元素的值 private static final Integer[] T = new Integer[64]; static { for (int i = 0; i < 64; i++) { double d = Math.abs(Math.sin(i + 1)); T[i] = (int) (d * (1L << 32)); } } // ... }
2、劃分數據:將填充後的數據劃分為多個512位的塊,然後對每個塊進行加密操作。
3、初始化變數:對每個塊進行加密操作之前,需要先對MD5加密演算法用到的四個變數進行初始化,這四個變數的初始值為固定值。
4、加密:將每個塊進行加密操作,每個塊的加密都是基於上一個塊的加密結果。最終的加密結果即為MD5值。
二、MD5加密演算法應用場景
MD5加密演算法在計算機領域中有著廣泛的應用場景,下面介紹三個典型的應用場景。
1、密碼存儲
MD5加密演算法可以用於密碼的存儲,通過將用戶輸入的明文密碼進行MD5加密,將加密後的結果存儲到資料庫中。當用戶下一次登錄時,再將輸入的密碼進行MD5加密,並與資料庫中的密文密碼進行比對,從而達到驗證用戶身份的目的。
public class PasswordUtils { /** * 對字元串進行MD5加密 * * @param src 待加密的字元串 * @return 加密後的字元串 */ public static String encrypt(String src) { MessageDigest md5; try { md5 = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } byte[] byteArray = src.getBytes(StandardCharsets.UTF_8); byte[] md5Bytes = md5.digest(byteArray); StringBuilder hexValue = new StringBuilder(); for (byte md5Byte : md5Bytes) { int val = ((int) md5Byte) & 0xff; if (val < 16) { hexValue.append("0"); } hexValue.append(Integer.toHexString(val)); } return hexValue.toString(); } // ... }
2、數字簽名
MD5加密演算法可以用於數字簽名,數字簽名是指用某個私鑰對信息進行簽名,再將簽名與信息一起發送給收件人,收件人使用對應的公鑰來驗證簽名的合法性。
public class DigitalSignatureUtils { /** * 對數據進行數字簽名 * * @param data 待簽名的數據 * @param privateKey 簽名私鑰 * @return 數字簽名 * @throws Exception */ public static byte[] sign(byte[] data, PrivateKey privateKey) throws Exception { Signature signature = Signature.getInstance("MD5withRSA"); signature.initSign(privateKey); signature.update(data); return signature.sign(); } /** * 驗證數字簽名 * * @param data 原始數據 * @param signature 簽名 * @param publicKey 驗證公鑰 * @return 驗證結果 * @throws Exception */ public static boolean verify(byte[] data, byte[] signature, PublicKey publicKey) throws Exception { Signature sig = Signature.getInstance("MD5withRSA"); sig.initVerify(publicKey); sig.update(data); return sig.verify(signature); } }
3、文件校驗
MD5加密演算法可以用於文件校驗,因為文件的MD5值是唯一的,這意味著當用戶想要下載一個文件時,可以先對文件的MD5值進行校驗,如果MD5值一致,則表明該文件是原來的文件,否則文件就被篡改了。
public class FileCheckUtils { /** * 計算文件MD5值 * * @param file 待計算MD5值的文件 * @return MD5值 * @throws Exception */ public static String getFileMD5(File file) throws Exception { FileInputStream fileInputStream = new FileInputStream(file); byte[] buffer = new byte[1024]; MessageDigest md5 = MessageDigest.getInstance("MD5"); int numRead; do { numRead = fileInputStream.read(buffer); if (numRead > 0) { md5.update(buffer, 0, numRead); } } while (numRead != -1); fileInputStream.close(); byte[] md5Bytes = md5.digest(); StringBuilder hexValue = new StringBuilder(); for (byte md5Byte : md5Bytes) { int val = ((int) md5Byte) & 0xff; if (val < 16) { hexValue.append("0"); } hexValue.append(Integer.toHexString(val)); } return hexValue.toString(); } }
三、MD5加密演算法存在的問題
雖然MD5加密演算法在很多應用場景中都得到了廣泛的應用,但由於一些歷史原因和技術問題,MD5加密演算法在某些場景下可能存在一些問題,下面介紹兩個MD5加密演算法存在的問題。
1、碰撞攻擊
在密碼存儲、數字簽名等場景中,MD5加密演算法被用於驗證數據的完整性、安全性,但實際上,MD5加密演算法可以被破解,因為它並不是完全無法反推。碰撞攻擊是指在輸入的任意兩個不同的數據中找到相同的MD5值的過程。目前針對MD5的碰撞攻擊已經非常成熟,因此在密碼存儲、數字簽名等場景中建議使用更為安全的加密演算法。
2、MD5彩虹表攻擊
彩虹表攻擊是指對密文進行預先計算,存儲在資料庫中的彩虹表中,然後進行賬號破解的攻擊方式。虹表都是提前計算好演算法,存放在一個表格里,由於在運算速度上,計算要比破解慢得多,因此,指定長度的幾乎所有明文可能,都可以構造一張包含其MD5值的彩虹表。因此,為了增強密碼的安全性,導入「鹽值」(即隨機數)後再進行MD5加密。
public class SaltMd5 { /** * 加鹽MD5加密 * * @param src 待加密的字元串 * @param salt 鹽值 * @return 鹽值加密後的字元串 */ public static String encrypt(String src, String salt) { return DigestUtils.md5Hex(salt + DigestUtils.md5Hex(src)); } }
總之,MD5加密演算法在現實生活中有著廣泛的應用場景,在使用時候,我們需要根據具體的業務場景來選擇加密方式,建議在密碼存儲、數字簽名等安全性要求比較高的場景下,不要使用MD5加密演算法。
原創文章,作者:VZOFB,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/333159.html