【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"));
    }
}

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

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

相关推荐
摇滚侠2 小时前
《SpringBoot 3:入门与应用实战》第 2 章 IOC 思想与实现 阅读笔记 1
spring boot·笔记·后端
山荷枝2 小时前
03-框架--Spring
java·后端·spring
ChaHae-In3 小时前
SpringBoot统一功能处理
java·spring boot·后端
coder!mq3 小时前
说几个常见的语法糖?
java·开发语言·算法
gugucoding3 小时前
38. 【Java】Stream API(下):高级操作与性能
java·开发语言
Lhan.zzZ3 小时前
在 Visual Studio 2022 中打造可扩展的动态链接库模块:从零搭建到原理解析
开发语言·c++·visual studio
SamChan904 小时前
PDF翻译API的JWT签名鉴权与速率限制设计:安全实战指南
网络·安全·pdf
心平气和量大福大4 小时前
android-实例-蒲公英-更新与安装-5-签名与生成APK
android·java·开发语言
码哥DFS4 小时前
构造函数、实例对象、对象原型 ----三者关系
开发语言·javascript·原型模式
952364 小时前
Spring-cloud配置中心
java·spring·spring cloud·微服务