一、消息摘要的定义
消息摘要(Message Digest)是加密术语中一种通过散列函数生成的【固定长度的字符串】。它是对任意长度的输入消息(如文件、字符串等)进行处理后产生的【固定长度的唯一标识符】
二、消息摘要的作用
完整性校验:通过生成消息的摘要值,可以在接收方对收到的消息进行相同的摘要计算,若摘要值相同,说明消息未被篡改;若摘要值不同,则表明消息可能被修改。
数字签名:消息摘要是数字签名算法的重要组成部分。发送方可以通过对消息摘要进行加密,生成数字签名,接收方则可以通过解密并对消息进行摘要比对,确保消息的真实性和完整性。
快速比较:由于消息摘要是固定长度且唯一的标识符,可以用它快速比较两条消息是否相同,而不需要逐字节比较消息内容。
常见的消息摘要算法有 MD5、SHA-1、SHA-256 等。尽管 MD5 和 SHA-1 已不再安全,SHA-256 及其他更高级的算法仍然被广泛使用。
三、摘要算法
3.1、SHA-256 (安全散列算法)
SHA名称来自于安全散列算法(英语:Secure Hash Algorithm)的缩写,一种密码散列函数算法标准,由美国国家安全局研发(NSA)。
它们的【摘要长度】(以比特计算)加在原名后面来命名:SHA-256,SHA-384和SHA-512。
SHA-256固定长度输出:无论输入的大小,输出总是 256 位(32 字节)
3.2、MD5 (信息摘要算法)
MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。
3.3、SHA-256和md5比较
特性 | SHA-256 | MD5 |
哈希输出长度 | 256 位(32 字节) | 128 位(16 字节) |
安全性 | 非常安全,适合密码学应用 | 不安全,已被淘汰 |
抗碰撞能力 | 极强,尚无实用碰撞攻击 | 已被破解,容易找到碰撞 |
应用场景 | 密码学、区块链、数字签名等 | 文件校验等非安全场景 |
速度 | 较慢,运算复杂 | 较快,运算轻量 |
设计者 | 美国国家安全局 (NSA) | Ronald Rivest |
发布日期 | 2001 | 1991 |
3.4、代码实现
3.4.1 sha-256
// SHA-256 java版本实现
import java.security.MessageDigest;
public class SHA256Example {
public static void main(String[] args) throws Exception {
String input = "hello";
// 获取 SHA-256 实例
MessageDigest digest = MessageDigest.getInstance("SHA-256");
// 计算哈希值
byte[] hash = digest.digest(input.getBytes("UTF-8"));
// 将字节数组转为十六进制字符串
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
System.out.println(hexString.toString()); // 输出64个字符的十六进制字符串
}
}
3.4.2、md5
import java.security.NoSuchAlgorithmException;
public class MD5Example {
public static void main(String[] args) {
String input = "Hello, World!";
try {
// 创建 MD5 算法的 MessageDigest 实例
MessageDigest md = MessageDigest.getInstance("MD5");
// 将输入字符串转换为字节数组并更新到摘要中
byte[] messageDigest = md.digest(input.getBytes("UTF-8"));
// 将字节数组转换为十六进制格式的字符串
StringBuilder hexString = new StringBuilder();
for (byte b : messageDigest) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0'); // 补零确保每个字节是两位数
}
hexString.append(hex);
}
// 输出 MD5 哈希值
System.out.println("MD5 Hash of '" + input + "': " + hexString.toString());
} catch (NoSuchAlgorithmException e) {
// 捕获当系统不支持 MD5 算法时的异常
System.err.println("MD5 Algorithm not found.");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
3.5、SHA-256输出长度为256位(32字节)转64长度的字符串
这是因为该输出使用了 十六进制(Hex)编码 表示。
1.SHA-256 输出的本质:SHA-256 的散列值是一个 256 位 的二进制数字,即 32 字节(每个字节 8 位)。
2.十六进制编码:为了更容易查看和传输,通常将二进制数据用十六进制表示。十六进制用 16 个字符来表示二进制(每个字符 4 位),因此每个字节(8 位)可以用 2 个十六进制字符表示。
3.长度计算:如果 SHA-256 的输出是 32 字节(256 位),使用十六进制编码时,每个字节需要 2 个十六进制字符来表示,因此最终的输出长度为64个字符的字符串
4.(每个字符 4 位):每个字符 4 位的概念是指在 十六进制(Hexadecimal)编码中,一个十六进制字符可以表示 4 位二进制数字。这是因为十六进制是一种基数为 16 的数制,范围从 0 到 F,而这些字符可以直接映射到二进制的 4 位表示