目录
- 前言
- 1、概述
- 2、文本消息摘要
- 3、文件消息摘要
前言
消息摘要(Message Digest),也称为哈希函数或哈希摘要,是一种通过对消息或数据进行算法处理而生成的固定长度的数据字符串。它的作用是为了校验数据的完整性和一致性。
消息摘要算法接受不同长度的消息作为输入,并生成具有固定长度的摘要输出。无论输入消息的长度是多少,摘要输出的长度是固定的。常见的消息摘要算法有MD5、SHA-1、SHA-256等。
消息摘要的主要特点包括:
- 唯一性: 相同的输入消息将始终生成相同的摘要输出。不同的输入消息生成的摘要输出几乎不可能相同。
- 不可逆性: 从摘要输出无法反推出原始的输入消息。摘要函数是单向的,不能从摘要推导出原始消息。
- 固定长度: 消息摘要算法生成的摘要输出具有固定的长度。不论输入消息的长度是多少,摘要输出的长度是固定的。
文件消息摘要是一种特殊形式的消息摘要,它是对文件内容进行计算得出的摘要值。文件消息摘要可用于校验文件的完整性,防止文件在传输或存储过程中被篡改或损坏,确保存储的文件没有被非法修改。
通常,计算文件消息摘要的步骤如下:
- 选择适当的消息摘要算法(例如,MD5、SHA-1、SHA-256等)。
- 将文件内容作为输入,使用所选的摘要算法计算出摘要值。
- 将生成的摘要值与预先计算的摘要值进行比较。如果两个摘要值匹配,则文件未被篡改或损坏。
1、概述
- 消息摘要(Message Digest)又称为数字摘要(Digital Digest)。
- 它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生。
- 为了保证文件或者值的安全,使用数字摘要生成的值是不可以篡改的。
无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。例如应用MD5算法摘要的消息有128个比特位,用SHA-1算法摘要的消息最终有160比特位的输出。
只要输入的消息不同,对其进行摘要以后产生的摘要消息也必不相同;但相同的输入必会产生相同的输出。
常见算法 :
- MD5算法 : 摘要结果16个字节, 转16进制后32个字节
- SHA1算法 : 摘要结果20个字节, 转16进制后40个字节
- SHA256算法 : 摘要结果32个字节, 转16进制后64个字节
- SHA512算法 : 摘要结果64个字节, 转16进制后128个字节
2、文本消息摘要
public class DigestUtil {
/**
* MD5 加密长度:32字节数量
*/
private final static String MD5 = "MD5";
/**
* SHA1 加密长度:40字节数量
*/
private final static String SHA1 = "SHA-1";
/**
* SHA256 加密长度:64字节数量
*/
private final static String SHA256 = "SHA-256";
/**
* SHA512 加密长度:128字节数量
*/
private final static String SHA512 = "SHA-512";
public static void main(String[] args) {
String input = "test";
// 消息摘要算法
System.out.println("MD5加密:" + encryptDigest(input, MD5));
System.out.println("SHA1加密:" + encryptDigest(input, SHA1));
System.out.println("SHA256加密:" + encryptDigest(input, SHA256));
System.out.println("SHA512加密:" + encryptDigest(input, SHA512));
}
/***
* 消息摘要算法,是单向、不可逆的
*
* @param input 消息类型
* @param algorithm 算法类型:MD5、SHA-1、SHA-256、SHA-512
* @return
*/
public static String encryptDigest(String input, String algorithm) {
try {
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
// 消息数字摘要
byte[] digest = messageDigest.digest(input.getBytes());
return toHex(digest);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("加密失败!");
}
}
private static String toHex(byte[] digest) {
// 创建对象用来拼接
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
// 转成 16进制
String s = Integer.toHexString(b & 0xff);
if (s.length() == 1) {
// 如果生成的字符只有一个,前面补0
s = "0" + s;
}
sb.append(s);
}
return sb.toString();
}
}
效果:
3、文件消息摘要
文件消息摘要的产生和文件名称没有关系,任意修改名称后摘要密文不会发生改变。
public class DigestUtil {
/**
* MD5 加密长度:32字节数量
*/
private final static String MD5 = "MD5";
/**
* SHA1 加密长度:40字节数量
*/
private final static String SHA1 = "SHA-1";
/**
* SHA256 加密长度:64字节数量
*/
private final static String SHA256 = "SHA-256";
/**
* SHA512 加密长度:128字节数量
*/
private final static String SHA512 = "SHA-512";
public static void main(String[] args) {
// 获取文件消息摘要
String filePath = "C:\\Users\\Desktop\\test.txt";
System.out.println("获取文件消息MD5摘要:" + getDigestFile(filePath, MD5));
System.out.println("获取文件消息SHA1摘要:" + getDigestFile(filePath, SHA1));
System.out.println("获取文件消息SHA256摘要:" + getDigestFile(filePath, SHA256));
System.out.println("获取文件消息SHA512摘要:" + getDigestFile(filePath, SHA512));
}
/**
* @param filePath
* @param algorithm
* @return
* @throws Exception
*/
private static String getDigestFile(String filePath, String algorithm) {
try {
FileInputStream fis = new FileInputStream(filePath);
int len;
byte[] buffer = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((len = fis.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
// 获取消息摘要对象
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
// 获取消息摘要
byte[] digest = messageDigest.digest(baos.toByteArray());
System.out.println("文件摘要-密文的字节长度:" + digest.length);
return toHex(digest);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("获取文件摘要失败!");
}
}
private static String toHex(byte[] digest) {
// 创建对象用来拼接
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
// 转成 16进制
String s = Integer.toHexString(b & 0xff);
if (s.length() == 1) {
// 如果生成的字符只有一个,前面补0
s = "0" + s;
}
sb.append(s);
}
return sb.toString();
}
}
效果: