1. 概述

MD5是一种广泛使用的加密哈希函数,它产生128位的哈希值。

在这篇文章中,我们将探讨使用各种Java库创建MD5哈希值的不同方法。

2. 使用MessageDigest类创建MD5

java.security.MessageDigest类提供了哈希功能。首先,我们需要根据想要使用的算法实例化MessageDigest

MessageDigest.getInstance(String Algorithm)

然后,我们可以使用update()函数多次更新消息摘要:

public void update(byte [] input)

当处理长文件时,可以多次调用这个函数。最后,我们需要使用digest()函数生成哈希代码:

public byte[] digest()

下面是一个示例,它为密码生成哈希并进行验证:

@Test
public void givenPassword_whenHashing_thenVerifying() 
  throws NoSuchAlgorithmException {
    String hash = "35454B055CC325EA1AF2126E27707052";
    String password = "ILoveJava";
        
    MessageDigest md = MessageDigest.getInstance("MD5");
    md.update(password.getBytes());
    byte[] digest = md.digest();
    String myHash = DatatypeConverter
      .printHexBinary(digest).toUpperCase();
        
    assertThat(myHash.equals(hash)).isTrue();
}

同样,我们也可以验证文件的校验和:

@Test
public void givenFile_generatingChecksum_thenVerifying() 
  throws NoSuchAlgorithmException, IOException {
    String filename = "src/test/resources/test_md5.txt";
    String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3";
        
    MessageDigest md = MessageDigest.getInstance("MD5");
    md.update(Files.readAllBytes(Paths.get(filename)));
    byte[] digest = md.digest();
    String myChecksum = DatatypeConverter
      .printHexBinary(digest).toUpperCase();
        
    assertThat(myChecksum.equals(checksum)).isTrue();
}

需要注意的是,MessageDigest不是线程安全的。因此,我们应该为每个线程使用新的实例。

3. 使用Apache Commons创建MD5

org.apache.commons.codec.digest.DigestUtils类让事情变得更简单。

让我们来看一个为密码哈希和验证的示例:

@Test
public void givenPassword_whenHashingUsingCommons_thenVerifying()  {
    String hash = "35454B055CC325EA1AF2126E27707052";
    String password = "ILoveJava";

    String md5Hex = DigestUtils
      .md5Hex(password).toUpperCase();
        
    assertThat(md5Hex.equals(hash)).isTrue();
}

4. 使用Guava创建MD5

另一种方法是使用com.google.common.io.Files.hash来生成MD5校验和:

@Test
public void givenFile_whenChecksumUsingGuava_thenVerifying() 
  throws IOException {
    String filename = "src/test/resources/test_md5.txt";
    String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3";
        
    HashCode hash = com.google.common.io.Files
      .hash(new File(filename), Hashing.md5());
    String myChecksum = hash.toString()
      .toUpperCase();
        
    assertThat(myChecksum.equals(checksum)).isTrue();
}

请注意,Hashing.md5已弃用。然而,根据官方文档这里,弃用的原因主要是出于安全考虑不建议使用MD5。这意味着如果我们需要与要求使用MD5的遗留系统集成,我们仍然可以使用此方法。否则,最好选择更安全的选项,如SHA-256

5. 总结

Java API和其他第三方库(如Apache Commons和Guava)提供了多种方式来生成MD5哈希。请根据项目需求和依赖关系明智地选择。

如往常一样,代码可以在GitHub上找到