概述
哈希算法将任意长度的数据映射为固定长度的哈希值。具有单向性、确定性、雪崩效应等特点。
目录
MD5
原理
MD5 (Message Digest Algorithm 5) 产生128位(16字节)哈希值。使用Merkle-Damgård结构。
技术规格
| 属性 | 值 |
|---|---|
| 输出长度 | 128位 (16字节) |
| 块大小 | 512位 |
| 安全级别 | 已不安全 ⚠️ |
| 状态 | 不应使用 |
应用场景
❌ 不应在新项目中使用,仅用于:
- 非安全场景的校验和
- 数据去重(非安全场景)
- 学习目的
性能影响
- 计算速度:快
- 内存占用:低
- CPU使用率:低
Java实现示例
java
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;
public class MD5Example {
public static String hash(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hashBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
// 转换为十六进制字符串
StringBuilder sb = new StringBuilder();
for (byte b : hashBytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public static String hash(byte[] input) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hashBytes = md.digest(input);
StringBuilder sb = new StringBuilder();
for (byte b : hashBytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public static void main(String[] args) throws Exception {
System.out.println("⚠️ 警告: MD5已不安全,仅用于演示");
String input = "测试数据";
String hash = hash(input);
System.out.println("输入: " + input);
System.out.println("MD5: " + hash);
System.out.println("长度: " + hash.length() + " 字符 (128位)");
}
}
安全建议
⚠️ 强烈建议:
- 不要用于安全相关场景
- 不要用于密码哈希
- 不要用于数字签名
- 迁移到SHA-256或更高
SHA-1
原理
SHA-1 (Secure Hash Algorithm 1) 产生160位(20字节)哈希值。同样基于Merkle-Damgård结构。
技术规格
| 属性 | 值 |
|---|---|
| 输出长度 | 160位 (20字节) |
| 块大小 | 512位 |
| 安全级别 | 已不安全 ⚠️ |
| 状态 | 不应使用 |
应用场景
❌ 不应在新项目中使用
性能影响
- 计算速度:快
- 内存占用:低
- CPU使用率:低
Java实现示例
java
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;
public class SHA1Example {
public static String hash(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] hashBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : hashBytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public static void main(String[] args) throws Exception {
System.out.println("⚠️ 警告: SHA-1已不安全,应迁移到SHA-256");
String input = "测试数据";
String hash = hash(input);
System.out.println("输入: " + input);
System.out.println("SHA-1: " + hash);
System.out.println("长度: " + hash.length() + " 字符 (160位)");
}
}
安全建议
⚠️ 强烈建议迁移到SHA-256
SHA-2系列
原理
SHA-2系列包括SHA-224、SHA-256、SHA-384、SHA-512等变体。使用Merkle-Damgård结构。
技术规格
| 算法 | 输出长度 | 块大小 | 字长 | 轮数 | 安全级别 |
|---|---|---|---|---|---|
| SHA-224 | 224位 | 512位 | 32位 | 64 | 高 |
| SHA-256 | 256位 | 512位 | 32位 | 64 | 推荐 |
| SHA-384 | 384位 | 1024位 | 64位 | 80 | 高 |
| SHA-512 | 512位 | 1024位 | 64位 | 80 | 高 |
应用场景
- 密码存储:结合PBKDF2、bcrypt等
- 数字签名:与RSA、ECDSA结合
- 区块链:比特币、以太坊
- 数据完整性:文件校验、传输验证
- TLS/SSL:证书指纹
- Git:对象哈希
性能影响
- 计算速度:快(SHA-256最快)
- 内存占用:低
- CPU使用率:低(某些CPU有硬件加速)
- 吞吐量:GB/s级别
Java实现示例
java
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class SHA2Example {
/**
* SHA-256哈希(最常用)
*/
public static String sha256(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hashBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hashBytes);
}
/**
* SHA-256哈希(返回Base64)
*/
public static String sha256Base64(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hashBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(hashBytes);
}
/**
* SHA-512哈希
*/
public static String sha512(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-512");
byte[] hashBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hashBytes);
}
/**
* SHA-384哈希
*/
public static String sha384(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-384");
byte[] hashBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hashBytes);
}
/**
* SHA-224哈希
*/
public static String sha224(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-224");
byte[] hashBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hashBytes);
}
/**
* 文件哈希(适合大文件)
*/
public static String hashFile(java.io.InputStream inputStream, String algorithm)
throws Exception {
MessageDigest md = MessageDigest.getInstance(algorithm);
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
md.update(buffer, 0, bytesRead);
}
return bytesToHex(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 boolean verifyIntegrity(String data, String expectedHash) throws Exception {
String actualHash = sha256(data);
return actualHash.equals(expectedHash);
}
/**
* 完整示例
*/
public static void main(String[] args) throws Exception {
String input = "这是要哈希的数据";
System.out.println("=== SHA-2系列哈希 ===");
System.out.println("输入: " + input);
System.out.println("SHA-224: " + sha224(input));
System.out.println("SHA-256: " + sha256(input));
System.out.println("SHA-384: " + sha384(input));
System.out.println("SHA-512: " + sha512(input));
System.out.println("\n=== 数据完整性验证 ===");
String data = "重要数据";
String hash = sha256(data);
System.out.println("数据: " + data);
System.out.println("哈希: " + hash);
System.out.println("验证结果: " + verifyIntegrity(data, hash));
System.out.println("\n=== 性能测试 ===");
String testData = "性能测试数据" + "x".repeat(10000);
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
sha256(testData);
}
long end = System.currentTimeMillis();
System.out.println("SHA-256 (1000次): " + (end - start) + "ms");
}
}
安全建议
✅ 推荐:
- SHA-256:最常用,性能与安全性平衡
- SHA-384:高安全需求
- SHA-512:极高安全需求
SHA-3系列
原理
SHA-3基于Keccak算法,使用海绵结构(Sponge Construction),不同于SHA-2的Merkle-Damgård结构。
技术规格
| 算法 | 输出长度 | 容量 | 安全级别 |
|---|---|---|---|
| SHA3-224 | 224位 | 448位 | 高 |
| SHA3-256 | 256位 | 512位 | 推荐 |
| SHA3-384 | 384位 | 768位 | 高 |
| SHA3-512 | 512位 | 1024位 | 高 |
应用场景
- 后量子密码学:作为SHA-2的替代
- 新项目:考虑使用SHA-3
- 区块链:某些新兴区块链
- 需要不同架构的场景
性能影响
- 计算速度:中等(比SHA-2稍慢)
- 内存占用:中等
- CPU使用率:中等
- 硬件加速:较少支持
Java实现示例
java
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;
public class SHA3Example {
/**
* SHA3-256哈希
*/
public static String sha3_256(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA3-256");
byte[] hashBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hashBytes);
}
/**
* SHA3-512哈希
*/
public static String sha3_512(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA3-512");
byte[] hashBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hashBytes);
}
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) throws Exception {
String input = "测试数据";
System.out.println("输入: " + input);
System.out.println("SHA3-256: " + sha3_256(input));
System.out.println("SHA3-512: " + sha3_512(input));
// 注意:SHA-3需要Java 9+,且需要支持SHA-3的提供者
}
}
安全建议
✅ 适用场景:
- 需要与SHA-2不同的算法结构
- 后量子密码学考虑
- 新项目可以考虑使用
⚠️ 注意:
- Java 9+支持
- 性能稍低于SHA-256
- 目前SHA-256仍然是最广泛使用的选择
BLAKE2
原理
BLAKE2是SHA-3竞赛的决赛算法之一,基于ChaCha流密码设计。有两个变体:BLAKE2b(64位)和BLAKE2s(32位)。
技术规格
| 变体 | 输出长度 | 块大小 | 优势 |
|---|---|---|---|
| BLAKE2b | 1-512位 | 128字节 | 64位平台优化 |
| BLAKE2s | 1-256位 | 64字节 | 32位平台优化 |
应用场景
- 高性能场景:需要比SHA-256更快
- 密码存储:Argon2使用BLAKE2b
- 文件校验:某些文件传输工具
- 区块链:某些加密货币
性能影响
- 计算速度:非常快(比SHA-256快)
- 内存占用:低
- CPU使用率:低
- 吞吐量:高于SHA-256
Java实现示例
arduino
// 注意:Java标准库不包含BLAKE2
// 需要使用第三方库,如Apache Commons Codec或BouncyCastle
import org.bouncycastle.jcajce.provider.digest.Blake2b;
import org.bouncycastle.util.encoders.Hex;
import java.nio.charset.StandardCharsets;
public class BLAKE2Example {
/**
* BLAKE2b哈希
*/
public static String blake2b(String input) {
Blake2b.Digest digest = new Blake2b.Digest(256); // 256位输出
byte[] hashBytes = digest.digest(input.getBytes(StandardCharsets.UTF_8));
return Hex.toHexString(hashBytes);
}
/**
* BLAKE2b自定义输出长度
*/
public static String blake2b(String input, int outputLength) {
Blake2b.Digest digest = new Blake2b.Digest(outputLength * 8);
byte[] hashBytes = digest.digest(input.getBytes(StandardCharsets.UTF_8));
return Hex.toHexString(hashBytes);
}
public static void main(String[] args) {
String input = "测试数据";
System.out.println("输入: " + input);
System.out.println("BLAKE2b-256: " + blake2b(input));
System.out.println("BLAKE2b-512: " + blake2b(input, 64));
}
}
安全建议
✅ 适用场景:
- 需要高性能哈希
- 密码派生函数(Argon2)
- 对性能有较高要求的场景
⚠️ 注意:
- 需要第三方库支持
- 不如SHA-256广泛支持
SM3 (国密算法)
原理
SM3是中国国家密码管理局发布的密码哈希算法,输出256位哈希值,基于Merkle-Damgård结构。
技术规格
| 属性 | 值 |
|---|---|
| 输出长度 | 256位 (32字节) |
| 块大小 | 512位 |
| 安全级别 | 高(国密标准) |
| 状态 | 国密标准 |
应用场景
- 政府系统:符合国密要求
- 金融行业:国内银行、支付
- 信创项目:国产化替代
- 数字签名:与SM2结合使用
性能影响
- 计算速度:快(与SHA-256相当)
- 内存占用:低
- CPU使用率:低
Java实现示例
java
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.MessageDigest;
import java.security.Security;
import java.nio.charset.StandardCharsets;
public class SM3Example {
static {
Security.addProvider(new BouncyCastleProvider());
}
public static String hash(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("SM3", "BC");
byte[] hashBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hashBytes);
}
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) throws Exception {
String input = "测试数据";
System.out.println("输入: " + input);
System.out.println("SM3: " + hash(input));
System.out.println("长度: " + hash(input).length() + " 字符 (256位)");
}
}
性能对比
哈希算法性能对比表
| 算法 | 输出长度 | 速度 | 硬件加速 | 推荐度 |
|---|---|---|---|---|
| SHA-256 | 256位 | 快 | 有 | ⭐⭐⭐⭐⭐ |
| SHA-512 | 512位 | 快 | 有 | ⭐⭐⭐⭐ |
| SHA3-256 | 256位 | 中等 | 少 | ⭐⭐⭐⭐ |
| BLAKE2b | 可变 | 很快 | 无 | ⭐⭐⭐⭐ |
| SM3 | 256位 | 快 | 少 | ⭐⭐⭐⭐ |
| SHA-1 | 160位 | 快 | 有 | ❌ |
| MD5 | 128位 | 快 | 有 | ❌ |
性能优化建议
- 选择SHA-256:性能与安全性最佳平衡
- 大文件哈希:使用流式处理,避免一次性加载
- 并行处理:大文件可以分块并行哈希
- 硬件加速:某些CPU支持SHA指令加速
哈希算法的应用模式
密码哈希(不使用纯哈希)
❌ 错误方式:
ini
String passwordHash = SHA256.hash(password); // 不安全!
✅ 正确方式:
ini
// 使用PBKDF2、bcrypt、Argon2等专门算法
String passwordHash = PBKDF2.hash(password, salt, iterations);
数据完整性验证
arduino
// 文件传输完整性
String fileHash = SHA256.hashFile(file);
// 存储哈希值,验证时重新计算并比较
数字指纹
ini
// 生成数据唯一标识
String fingerprint = SHA256.hash(data);
去重
ini
// 非安全场景的数据去重
Set<String> hashSet = new HashSet<>();
String hash = SHA256.hash(data);
if (!hashSet.contains(hash)) {
// 新数据
}
总结
推荐选择
通用场景:
- 首选:SHA-256(最广泛使用)
- 高安全:SHA-384 或 SHA-512
特殊场景:
- 高性能需求:BLAKE2b
- 国密合规:SM3
- 新项目考虑:SHA3-256
不应使用:
- ❌ MD5
- ❌ SHA-1
选择决策树
需要哈希算法?
├─ 需要国密合规?→ SM3
├─ 性能优先?→ BLAKE2b
├─ 通用场景?→ SHA-256
└─ 高安全需求?→ SHA-384/512