【Java】Argon2实现密码加密以及在springboot中使用教程

前言

  密码加密是每个计算机软件系统都绕不开的话题,加密也有很多种方式,选择加密方式需要从安全性、可靠性、性能等多方面综合考虑,在众多加密方式中Argon2是一个非常优秀的方案,下面是主流的一些加密方式对比

特性 Argon2id bcrypt scrypt PBKDF2
核心机制 同时消耗 CPU + 内存,且内存访问顺序混合 基于Blowfish加密,仅消耗 CPU 消耗 大量内存(需构造伪随机序列) 仅消耗 CPU(反复执行HMAC)
抗GPU/ASIC 极强(内存成本极高,难以并行) 中等(内存占用仅4KB,易被FPGA/GPU加速) 强(内存占用大,受限于内存带宽) 极弱(内存占用极低,GPU可暴力破解)
可调参数 3个(时间t、内存m、并行度p) 1个(工作因子cost) 2个(CPU成本N、内存成本r) 1个(迭代次数)
默认内存占用 19 MiB(建议值) 4 KB(固定极小) 16 MB+(可调大) 极低(可忽略)
侧信道攻击 Argon2id 混合模式可抵抗 部分抵抗 抵抗 抵抗
优点 安全性最高,抗GPU/ASIC攻击能力最强 成熟稳定,广泛使用,内置盐值 安全性高,有效抵抗硬件暴力破解 合规性好

Argon2是什么?

  Argon2 是当前最先进、最推荐的密码哈希算法。它是2015年"密码哈希竞赛"的冠军,设计上就是为了对抗现代GPU和ASIC破解硬件。它允许你独立配置时间成本、内存成本和并行度三个参数,灵活性极高,并于2021年正式成为IETF标准(RFC 9106)

Argon2有三种变体,各自有不同的应用场景:

变体 说明
Argon2d 使用数据依赖的内存访问方式。它的速度最快,对GPU和ASIC破解的抵抗性最强,但由于内存访问模式与数据相关,容易受到侧信道攻击。因此,它适用于没有侧信道攻击威胁的场景,比如加密货币。
Argon2i 使用数据独立的内存访问方式。它专门为抵抗侧信道攻击而设计,更适合密码哈希和基于密码的密钥派生。但它的安全性略低于Argon2d。
Argon2id 混合模式,也是官方推荐和默认的变体。它结合了前两者的优点:前半部分使用Argon2i(抵抗侧信道),后半部分使用Argon2d(抵抗GPU破解)。对于绝大多数场景,尤其是密码存储,你应该选择 Argon2id。

Argon2id在springboot中使用

引入argon2依赖

xml 复制代码
 <dependency>
    <groupId>de.mkammerer</groupId>
     <artifactId>argon2-jvm</artifactId>
     <version>2.11</version>
 </dependency>

实现工具类,该工具类可以直接复制使用,简单易懂,根据项目实际情况配置一下参数即可以实现加密和验证操作。

java 复制代码
import de.mkammerer.argon2.Argon2;
import de.mkammerer.argon2.Argon2Factory;
/**
 * Argon2 是当前推荐的密码哈希算法(密码哈希竞赛冠军),Argon2id 兼顾抗 GPU 与侧信道攻击,适合存储用户密码
 */
public class Argon2IdUtil {

    // 构建 Argon2id(自动加盐)
    private static final Argon2 ARGON2 = Argon2Factory.create(Argon2Factory.Argon2Types.ARGON2id);

    // 哈希参数, 低配置:3, 65536, 4,高安全:4, 131072, 8(消耗内存更多)服务端可按需调整,内存越大越安全
    //迭代次数
    private static final int ITERATIONS = 3;
    //内存(KB)
    private static final int MEMORY = 65536;
    //并行度
    private static final int PARALLELISM = 4;


    /**
     * 生成密码哈希
     * @param rawPassword 原始明文密码
     * @return 哈希字符串(内置salt,直接入库)
     */
    public static String hash(String rawPassword) {
        char[] chars = rawPassword.toCharArray();
        try {
            return ARGON2.hash(ITERATIONS, MEMORY, PARALLELISM, chars);
        } finally {
            // 清空内存明文,防止密码残留
            ARGON2.wipeArray(chars);
        }
    }

    /**
     * 校验密码
     * @param hash 数据库存储的hash
     * @param rawPassword 前端传入明文
     * @return 是否匹配
     */
    public static boolean verify(String hash, String rawPassword) {
        char[] chars = rawPassword.toCharArray();
        try {
            return ARGON2.verify(hash, chars);
        } finally {
            ARGON2.wipeArray(chars);
        }
    }

    public static void main(String[] args) {
    	String hash = Argon2IdUtil.hash("123456");
    	System.out.println("加密后的密文:"+hash);
    	System.out.println("校验密码:"+Argon2IdUtil.verify(hash, "123456"));
    }
}

运行上面工具类,结果如下:

为了帮助更多像你一样的读者,我将持续在专栏中分享技术干货和实用技巧。如果你觉得这篇文章对你有帮助,可以考虑关注我的专栏,谢谢。

相关推荐
智慧物业老杨1 小时前
物业日常巡查的数智化重构:从“打卡式巡检“到“闭环式风控“
android·java·人工智能·系统架构·rxjava
晴天的雨.9922 小时前
【C++算法】和为s的两个数
开发语言·数据结构·c++·算法
IvanCodes7 小时前
Python 数据处理(十三):JSON、CSV 与数据序列化
开发语言·python
红姐跨境书7 小时前
从零打造高性能 API 网关: Go 语言中的双缓冲 Dynamic Config 最佳实践
安全
步行cgn8 小时前
Spring c 命名空间注入详解
java·后端·spring
明月_清风8 小时前
Maven 到底是什么?一篇文章搞懂 Java 项目构建与依赖管理
java·后端·maven
aramae8 小时前
MySQL复合查询(8)
java·c语言·开发语言·后端·算法
Rain的Java大神之路9 小时前
如何快速上传10G文件
java·spring boot·redis·后端·mysql·spring cloud·面试
Wang's Blog9 小时前
Java 接入Redis: 通用命令与键管理
java·服务器·redis
Wang's Blog9 小时前
Java 接入Redis: 列表集合与有序集合操作命令
java·服务器·redis