以下是使用 Argon2 算法的 Java 实现,用于安全密码哈希存储。Argon2 是密码哈希竞赛(PHC)的获胜者,被公认为当前最安全的密码哈希算法之一。


1. 添加依赖

首先,在 pom.xml 中添加 Bouncy CastleArgon2 JVM 支持:

选项1:Bouncy Castle(推荐)

1
2
3
4
5
6
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>

选项2:Argon2 JVM

1
2
3
4
5
6
<dependency>
<groupId>de.mkammerer</groupId>
<artifactId>argon2-jvm</artifactId>
<version>2.11</version>
</dependency>


2. 完整代码实现(基于 Bouncy Castle)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import org.bouncycastle.crypto.generators.Argon2BytesGenerator;
import org.bouncycastle.crypto.params.Argon2Parameters;
import java.security.SecureRandom;
import java.util.Base64;

public class Argon2PasswordHasher {

// Argon2 配置参数(可根据硬件性能调整)
private static final int ITERATIONS = 10; // 迭代次数
private static final int MEMORY = 65536; // 内存消耗(KB)
private static final int PARALLELISM = 1; // 并行线程数
private static final int SALT_LENGTH = 16; // 盐值长度(字节)
private static final int HASH_LENGTH = 32; // 哈希输出长度(字节)

/**
* 生成 Argon2 哈希密码(格式:盐值:哈希值)
*/
public static String hashPassword(String password) {
// 生成随机盐值
byte[] salt = generateSalt(SALT_LENGTH);

// 配置 Argon2 参数
Argon2Parameters.Builder builder = new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id)
.withSalt(salt)
.withIterations(ITERATIONS)
.withMemoryAsKB(MEMORY)
.withParallelism(PARALLELISM);

// 生成哈希
Argon2BytesGenerator generator = new Argon2BytesGenerator();
generator.init(builder.build());
byte[] hash = new byte[HASH_LENGTH];
generator.generateBytes(password.toCharArray(), hash);

// 返回 Base64 编码的盐值和哈希
return Base64.getEncoder().encodeToString(salt) + ":" +
Base64.getEncoder().encodeToString(hash);
}

/**
* 验证密码
*/
public static boolean verifyPassword(String inputPassword, String storedHash) {
// 拆分盐值和哈希
String[] parts = storedHash.split(":");
byte[] salt = Base64.getDecoder().decode(parts[0]);
byte[] originalHash = Base64.getDecoder().decode(parts[1]);

// 使用相同盐值重新计算哈希
Argon2Parameters.Builder builder = new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id)
.withSalt(salt)
.withIterations(ITERATIONS)
.withMemoryAsKB(MEMORY)
.withParallelism(PARALLELISM);

Argon2BytesGenerator generator = new Argon2BytesGenerator();
generator.init(builder.build());
byte[] newHash = new byte[HASH_LENGTH];
generator.generateBytes(inputPassword.toCharArray(), newHash);

// 对比哈希值
return MessageDigest.isEqual(originalHash, newHash);
}

/**
* 生成随机盐值
*/
private static byte[] generateSalt(int length) {
SecureRandom random = new SecureRandom();
byte[] salt = new byte[length];
random.nextBytes(salt);
return salt;
}

// 测试示例
public static void main(String[] args) {
String password = "MySecurePassword123!";

// 哈希密码
String hashedPassword = hashPassword(password);
System.out.println("Hashed Password: " + hashedPassword);

// 验证密码
boolean isValid = verifyPassword(password, hashedPassword);
System.out.println("Password Valid: " + isValid); // true

isValid = verifyPassword("WrongPassword", hashedPassword);
System.out.println("Wrong Password Valid: " + isValid); // false
}
}

3. 关键参数说明

参数 推荐值 作用
ITERATIONS 10-20 增加计算时间,防御暴力破解
MEMORY 64MB-1GB (65536 KB) 增加内存消耗,防御GPU/ASIC攻击
PARALLELISM 1-2 并行线程数(通常1即可)
SALT_LENGTH 16字节 确保每个密码哈希唯一
HASH_LENGTH 32字节 输出哈希长度(与SHA-256一致)

4. 为什么选择 Argon2?

  1. 抗GPU/ASIC:内存密集型设计,显著增加硬件攻击成本。
  2. 灵活配置:可调整时间/内存/线程参数,适应不同硬件。
  3. PHC获胜者:学术界和工业界公认的最安全密码哈希算法。

5. 注意事项

• 参数调优:根据服务器性能调整 ITERATIONSMEMORY(目标:哈希耗时约0.5-1秒)。

• 密码编码:建议明确指定字符集(如 password.getBytes(StandardCharsets.UTF_8))。

• 依赖更新:定期检查 Bouncy Castle 的安全公告


6. 性能对比(示例)

算法 哈希耗时(1核CPU) 抗GPU攻击能力
SHA-256 0.01ms
PBKDF2 100ms ⚠️中等
Argon2 500ms ✅最强

以上实现可直接用于生产环境,如需进一步强化,可结合加密(如AES)存储盐值。