程序员的资源宝库

网站首页 > gitee 正文

Java 实现密码添加随机盐进行 MD5 摘要加密(2021/05/11)

sanyeah 2024-04-12 17:40:14 gitee 3 ℃ 0 评论

Java 实现密码添加随机盐进行 MD5 摘要加密(2021/05/11)

目录
  • Java 实现密码添加随机盐进行 MD5 摘要加密(2021/05/11)
    • 1. 概述
    • 2. 环境准备
    • 3. MD5 摘要算法
    • 4. MD5 + 盐摘要算法

1. 概述

在日常开发中,经常面临用户密码的保存问题,一定不能明文存储密码到数据库,可以采用哈希摘要算法加密密码,再保存到数据库。

哈希摘要算法:只能从明文生成一个对应的哈希值,不能反过来根据哈希值得到对应的明文。

2. 环境准备

本文使用的所有生成摘要算法的方法都来自于 Hutool 工具包,Hutool 是一个小而全的 Java 工具类库,封装了一些静态方法,降低了相关 API 的学习成本,想要详细了解的话可以去阅读其官方文档。

笔者此处通过 Maven 的方式导入依赖:

<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.6.5</version>
</dependency>

3. MD5 摘要算法

MD5 是一种非常经典的哈希摘要算法,被广泛应用于数据完整性的校验、数据摘要、数据加密等。

来看一个简单的例子,如下:

@Test
public void MD5Test() {
    String password = "abc123456";
    String md5 = DigestUtil.md5Hex(password);
    System.out.println("md5 = " + md5);
}

运行结果:

md5 = 0659c7992e268962384eb17fafe88364

可以看到密码进行了摘要加密,已经无法直接获取明文密码,但是如果我们摘要结果输入到 MD5 免费破解网站,马上就能获取到原密码了。

想象一下,如果黑客构建一个超级大的数据库,把所有 20 位数字以内的数字和字母组合的密码全部计算 MD5 哈希值出来,并且把密码和它们对应的哈希值存到里面去(即彩虹表)。在破解密码的时候,只需要查一个这个彩虹表就完事了。所以单单 MD5 对密码取哈希值存储已经不安全了。

4. MD5 + 盐摘要算法

加盐:在密码学中,是指通过在密码任意固定位置插入特定的字符串,让散列后的结果和使用原始密码的散列结果不相符,这种过程称之为”加盐“。

用户密码 + 盐之后,进行哈希散列,再保存到数据库,这样可以有效应对彩虹表破解法,但是使用加盐,需要注意以下几点:

  • 不能在代码中写死盐,且盐需要有一定的长度(盐写死太简单的话,黑客可能注册几个账号反推出来);
  • 每一个密码都有独立的盐,并且盐要长一点,比如超过 20 位(盐太短,加上原始密码太短,容易破解);
  • 最好是随机的值,并且是全球唯一的,意味着全球不可能有现成的彩虹表给你用;

此处笔者提供一种思路,对每一条用户密码生成唯一的 UUID 当作其盐值拼接在用户密码后边,然后对用户密码 + 盐进行 MD5 摘要加密,将加密后的哈希值与 UUID 通过一定的算法组合在一起存入数据库,便于在验证密码时能够从数据库中反解出 UUID。

具体实现代码如下:

import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.digest.DigestUtil;

/**
 * 安全工具类.
 *
 * @author <a href="mailto:xiaoQQya@126.com">xiaoQQya</a>
 * @version 1.0
 * @date 2021/04/07
 * @since 1.0
 */
public class SecureUtil {

    private static final int PASSWORD_AND_SALT_LENGTH = 64;

    /**
     * 生成含有随机盐的密码.
     *
     * @param password 密码
     * @return 含有随机盐的密码 MD5 值
     * @author xiaoqqya
     * @date 2021/04/07
     */
    public static String generate(String password) {
        String salt = IdUtil.simpleUUID();
        password = DigestUtil.md5Hex(password + salt);
        char[] md5 = new char[PASSWORD_AND_SALT_LENGTH];
        for (int i = 0; i < PASSWORD_AND_SALT_LENGTH; i++) {
            md5[i] = password.charAt(i / 2);
            md5[++i] = salt.charAt(i / 2);
        }
        return new String(md5);
    }

    /**
     * 校验密码是否正确.
     *
     * @param password 密码
     * @param md5      带有随机盐的密码 MD5 值
     * @return 密码是否正确
     * @author xiaoqqya
     * @date 2021/04/07
     */
    public static boolean verify(String password, String md5) {
        char[] pwd = new char[32];
        char[] salt = new char[32];
        for (int i = 0; i < PASSWORD_AND_SALT_LENGTH; i++) {
            pwd[i / 2] = md5.charAt(i);
            salt[i / 2] = md5.charAt(++i);
        }
        return DigestUtil.md5Hex(password + new String(salt)).equals(new String(pwd));
    }
}

参考链接:

  • 如何安全传输存储用户密码:https://mp.weixin.qq.com/s/dIPL4TK43l360aXX2uRMLw

相关链接:

  • Hutool 官网:https://www.hutool.cn/
  • Hutool 参考文档:https://www.hutool.cn/docs/#/
  • Hutool API 文档:https://apidoc.gitee.com/dromara/hutool/
  • MD5 免费解密:https://www.somd5.com/

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表