我以前使用的都是md5加盐存储用户密码,但是我们老师说md5不安全。然后我开始找一个相对安全的加密算法,最后找到了
BCrypt
算法。
如果在Java中想使用BCrypt加密算法,有两种途径:
- 使用
springsecurity
- 使用
org.mindrot.jbcrypt
我这篇文章用org.mindrot.jbcrypt
演示BCrypt加密算法的使用。
1.创建简单的maven项目
项目结构:
pom.xml:
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.akbar</groupId>
<artifactId>bcrypt-project</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<!--引入jbcrypt坐标-->
<groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId>
<version>0.4</version>
</dependency>
</dependencies>
</project>
2.使用bcrypt算法
java
package com.akbar;
import org.mindrot.jbcrypt.BCrypt;
public class Main {
public static void main(String[] args) {
String password = "123";
// 生成加密哈希
String hashed = BCrypt.hashpw(password, BCrypt.gensalt());
System.out.println(hashed);
// 验证密码
boolean match = BCrypt.checkpw(password, hashed);
if (match) {
System.out.println("密码正确");
} else {
System.out.println("密码不正确");
}
}
}
3.jbcryp关键方法
方法 | 作用 |
---|---|
hashpw(String password, String salt) |
使用 salt 对 password 进行加密 |
gensalt(int log_rounds) |
生成带有 log_rounds 计算成本的 salt |
gensalt() |
生成默认 10 轮加密的 salt |
checkpw(String plaintext, String hashed) |
验证 password 是否匹配 hashed |
gensalt()解读
gensalt()
是 bcrypt
计算的核心,决定了哈希强度。
默认使用:
java
String salt = BCrypt.gensalt(); // 默认 log_rounds = 10
System.out.println("Salt: " + salt);
自定义计算成本:
java
String salt = BCrypt.gensalt(12); // 使用 12 轮计算成本
System.out.println("Salt: " + salt);
gensalt(12)
计算成本 12
,比 10
更安全但计算更慢。
checkpw() 如何验证密码
java
String password = "123";
// 生成加密哈希
String hashed = BCrypt.hashpw(password, BCrypt.gensalt());
// 验证密码
boolean match = BCrypt.checkpw(password, hashed);
🔹 不能直接用 equals()
比较密码 ,因为 bcrypt
每次生成的哈希都不同。
🔹 checkpw()
内部会自动解析 salt
并进行比较。
hashpw() 解析哈希格式
bcrypt 生成的哈希是 60 个字符的字符串,格式如下:
perl
$2a$10$qO6PDKpRBK6N7d8GxOpCAO58wSINRdBSQ4kB2Jm3y85nKuqcqdSxa
解析结构(为了容易区分,用空格隔开):
perl
$2a$ 10 $qO6PDKpRBK6N7d8GxOpCAO58wSINRdBSQ4kB2Jm3y85nKuqcqdSxa
│ │ │ └─────────── 哈希值(bcrypt 计算后)
│ │ └─────────── Salt(前 16 字符)
│ └────── 计算成本(log_rounds = 10)
└──── bcrypt 版本号($2a$ 代表标准 bcrypt)
🔹 bcrypt
的特性: 即使 password
相同,每次哈希都不同 。
🔹 安全性来源 :哈希值包含 动态 salt
,所以无法用 hashmap
预计算彩虹表攻击。