如何在Java中为文件生成 MD5 校验和?
一个 字母数字值,即唯一定义文件内容的字母和数字序列称为校验和(通常称为散列)。校验和通常用于检查从外部源下载的文件的完整性。如果您知道原始版本的校验和,您可以使用校验和实用程序来确保您的副本是等效的。例如,在备份文件之前,您可以生成这些文件的校验和,并且可以在必须将它们下载到其他设备上时进行验证。如果文件在此过程中已损坏或更改,则校验和会有所不同。
MD5 和 SHA 是两种最广泛使用的校验和算法。您必须确保在检查校验和时使用与用于生成校验和的算法相同的算法。例如,文件的 MD5 校验和值与其 SHA-256 校验和值完全不同。
要生成校验和,您需要运行一个程序,通过算法将该文件放入。用于此的典型算法包括 MD5、SHA-1、SHA-256 和 SHA-512。
这些算法使用加密散列函数,该函数接受输入并生成固定长度的字母数字字符串,而不管文件的大小。
NOTE:
- Even small changes in the file will produce a different checksum.
- These cryptographic hash functions, though, aren’t flawless. “Collisions” with the MD5 and SHA-1 functions have been discovered by security researchers. They’ve found two different files, that produce the same MD5 or SHA-1 hash, but are different. This is highly unlikely to happen by mere accident, but this strategy may be used by an attacker to mask a malicious file as a valid file.
在Java中生成校验和
Java提供了通过Java安全包中的 MessageDigest 类生成这些散列函数的内置功能。消息摘要是加密的单向散列函数,它采用任意大小的数据并产生固定长度的散列值。
- 我们首先通过传递任何有效的散列算法字符串来实例化 MessageDigest 对象。
- 然后我们更新这个对象,直到我们读取完整的文件。尽管我们可以使用digest(byte[] input),它通过一次读取整个文件来创建MessageDigest 对象的最终更新,以防文件太大/太大,但我们可能没有足够的内存来读取整个文件作为字节数组,这可能会导致Java.lang.OutOfMemoryError: Java Heap Space 。
- 所以,最好是分段读取数据并更新MessageDigest。
更新完成后,将调用其中一种摘要方法来完成哈希计算。每当调用摘要方法时,MessageDigest 对象都会重置为其初始化状态。摘要方法返回一个字节数组,其中包含十进制格式的字节,因此我们将其转换为十六进制格式。最后一个字符串是校验和。
例子:
Java
// Java program to Generate MD5 Checksum for Files
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class GFG {
// this method gives a NoSuchAlgorithmException in case
// we pass a string which dosen't have any hashing
// algorithm in its correspondence
public static void main(String[] args)
throws IOException, NoSuchAlgorithmException
{
// create a file object referencing any file from
// the system of which checksum is to be generated
File file = new File("C:\\Users\\Raghav\\Desktop\\GFG.txt");
// instantiate a MessageDigest Object by passing
// string "MD5" this means that this object will use
// MD5 hashing algorithm to generate the checksum
MessageDigest mdigest = MessageDigest.getInstance("MD5");
// Get the checksum
String checksum = checksum(mdigest, file);
// print out the checksum
System.out.println(checksum);
}
// this method return the complete hash of the file
// passed
private static String checksum(MessageDigest digest,
File file)
throws IOException
{
// Get file input stream for reading the file
// content
FileInputStream fis = new FileInputStream(file);
// Create byte array to read data in chunks
byte[] byteArray = new byte[1024];
int bytesCount = 0;
// read the data from file and update that data in
// the message digest
while ((bytesCount = fis.read(byteArray)) != -1)
{
digest.update(byteArray, 0, bytesCount);
};
// close the input stream
fis.close();
// store the bytes returned by the digest() method
byte[] bytes = digest.digest();
// this array of bytes has bytes in decimal format
// so we need to convert it into hexadecimal format
// for this we create an object of StringBuilder
// since it allows us to update the string i.e. its
// mutable
StringBuilder sb = new StringBuilder();
// loop through the bytes array
for (int i = 0; i < bytes.length; i++) {
// the following line converts the decimal into
// hexadecimal format and appends that to the
// StringBuilder object
sb.append(Integer
.toString((bytes[i] & 0xff) + 0x100, 16)
.substring(1));
}
// finally we return the complete hash
return sb.toString();
}
}
输出:
8eeecb74627e963d65d10cbf92a2b7c9