RFC 1321中定义的MD5是一种哈希算法,可将输入转换为哈希值的固定128位(16字节)长度。
注意
MD5不是抗冲突的–两个不同的输入可能会产生相同的哈希值。 阅读此MD5漏洞 。 有许多快速安全的哈希算法,例如SHA3-256或BLAKE2 ; 对于密码哈希,我们可以使用Bcrypt或Argon2 。 如果可能,请勿在任何与安全性有关的加密任务中使用MD5。
在Java中,我们可以使用MessageDigest
生成MD5
算法。
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] result = md.digest(input);
1. Java MD5哈希
此Java示例使用MD5
从字符串生成哈希值。
MD5Utils.java
package com.mkyong.crypto.hash;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Utils {
private static final Charset UTF_8 = StandardCharsets.UTF_8;
private static final String OUTPUT_FORMAT = "%-20s:%s";
private static byte[] digest(byte[] input) {
MessageDigest md;
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException(e);
}
byte[] result = md.digest(input);
return result;
}
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public static void main(String[] args) {
String pText = "Hello MD5";
System.out.println(String.format(OUTPUT_FORMAT, "Input (string)", pText));
System.out.println(String.format(OUTPUT_FORMAT, "Input (length)", pText.length()));
byte[] md5InBytes = MD5Utils.digest(pText.getBytes(UTF_8));
System.out.println(String.format(OUTPUT_FORMAT, "MD5 (hex) ", bytesToHex(md5InBytes)));
// fixed length, 16 bytes, 128 bits.
System.out.println(String.format(OUTPUT_FORMAT, "MD5 (length)", md5InBytes.length));
}
}
输出量
Terminal
Input (string) :Hello MD5
Input (length) :9
MD5 (hex) :e5dadf6524624f79c3127e247f04b548
MD5 (length) :16
尝试另一个String,例如Hello MD5 Hello MD5
。 输入长度有所不同,但是MD5哈希值的输出仍然是128位16字节。
输出量
Terminal
Input (string) :Hello MD5 Hello MD5
Input (length) :19
MD5 (hex) :6219b1bc3542949e012616059409f1cc
MD5 (length) :16
2. Java MD5文件校验和。
对于文件校验和,想法是相同的,但是我们需要一些额外的IO类来处理输入流。
这是一个文本文件。
c:\\test\\readme.txt
Hello MD5
该Java程序将从文件生成MD5文件校验和。
MD5Utils.java
package com.mkyong.crypto.hash;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Utils {
private static final Charset UTF_8 = StandardCharsets.UTF_8;
private static final String OUTPUT_FORMAT = "%-20s:%s";
private static byte[] checksum(String filePath) {
MessageDigest md;
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException(e);
}
try (InputStream is = new FileInputStream(filePath);
DigestInputStream dis = new DigestInputStream(is, md)) {
while (dis.read() != -1) ; //empty loop to clear the data
md = dis.getMessageDigest();
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
return md.digest();
}
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public static void main(String[] args) {
String file = "c:\\test\\readme.txt";
System.out.println(String.format(OUTPUT_FORMAT, "Input (file) ", file));
System.out.println(String.format(OUTPUT_FORMAT, "MD5 (checksum hex) ", bytesToHex(checksum(file))));
}
}
输出量
Terminal
Input (file) :c:\test\readme.txt
MD5 (checksum hex) :e5dadf6524624f79c3127e247f04b548
3. Apache Commons编解码器
本示例使用commons-codec
库生成MD5哈希值。
pom.xml
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.14</version>
</dependency>
3.1来自字符串的MD5哈希值。
import org.apache.commons.codec.digest.DigestUtils;
String pText = "Hello MD5";
System.out.println(DigestUtils.md5Hex(password));
输出量
Terminal
e5dadf6524624f79c3127e247f04b548
3.2文件中的MD5哈希值。
try (InputStream is = new FileInputStream("c:\\test\\readme.txt")) {
String checksum = DigestUtils.md5Hex(is);
System.out.println(checksum);
} catch (IOException e) {
e.printStackTrace();
}
输出量
Terminal
e5dadf6524624f79c3127e247f04b548
下载源代码
$ git clone https://github.com/mkyong/core-java
$ cd java-crypto