Java中使用加密盐

0 前言

众所周知,密码肯定不能用明文存储。

之前一直使用MD5进行加密,现在才知道有彩虹表这回事。所以记录一下对应的处理方式:加密盐。

1 彩虹表

例如用MD5加密,随便没法破解,但是有些常用的字符被收集到彩虹表里那就危险了。

例如:123456使用MD5加密(32小写)后为:e10adc3949ba59abbe56e057f20f883e

一旦这个字符串被泄露,那么使用这个密码的用户就有极大的风险。

2 加密盐

加密盐(Salt)是一种在密码学中用于增加密码存储安全性的技术。盐通常是一个随机生成的字符串,它被添加到原始密码的前端、后端或嵌入到密码中间,然后再与密码一起进行哈希运算。这样做的目的是为了增加密码破解的难度,特别是针对彩虹表攻击(一种预先计算好的哈希值对照表,用于快速查找密码)和暴力破解攻击。

2.1 手搓加密盐

2.1.1 密码加盐(加密)

输入密码

产生盐值 -> 唯一字符串

盐值拼接字符串 生成加盐后的密码

加盐后的密码再次拼接输入的密码,生成最终的密文

2.1.2 密码验证

输入用户+密码

查出用户的密码

密码分割,找出密码的盐值

用户输入的密码+盐值 进行加密

拼接后 得到的加密值与查出的密码进行对比验证

后续操作

2.1.3 工具类

   /**
     * 1.加盐并生成最终的密码
     *
     * @param password 明文的密码
     * @return 最终生成的密码
     */
    public static String encrypt(String password) {
        //a.产生盐值
        //UUID.randomUUID()会生成32位数字+4位-,是随机的唯一的,将4位-去掉就得到32位数字的盐值
        String salt = UUID.randomUUID().toString().replace("-", "");
        //生成加盐后的密码(需要使用MD5)
        String saltPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
        //生成最终的密码格式
        String finalPassword = salt + "#" + saltPassword;
        return finalPassword;
    }

    /**
     * 2.加盐并生成最终密码格式(方法一的重载),区别于上面的方法:这个方法是用来解密的,给定了盐值,生成一个最终密码,
     * 后面要和正确的最终密码进行比对
     *
     * @param password 需要验证的明文密码
     * @param salt
     * @return
     */
    public static String encrypt(String password, String salt) {
        //1.生成一个加密后的密码
        String saltPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
        //2.生成最终的密码(待验证)
        String finalPassword = salt + "#" + saltPassword;
        return finalPassword;
    }

    /**
     * 3.验证密码
     *
     * @param inputPassword 登录用户输入的明文密码
     * @param finalPassword 数据库中实际的最终密码格式
     * @return
     */
    public static boolean check(String inputPassword, String finalPassword) {
        //首先判断这两个参数到底有没有值,数据库中的最终密码是不是65位
        if (StringUtils.hasLength(inputPassword) && StringUtils.hasLength(finalPassword)
                && finalPassword.length() == 65) {
            //a.首先从最终的密码中得到盐值
            //使用$将finalPassword划分成两个部分,前面的32位的部分就是盐值
            //注意:这里的#是被认为是一个通配符,所以要转义一下
            String salt = finalPassword.split("\\#")[0];
            //b.使用之前加密的方法,生成最终的密码格式(待验证)
            String checkPassword = encrypt(inputPassword, salt);
            if (checkPassword.equals(finalPassword)) {
                return true;
            }
        }
        return false;
    }

2.1.4 验证

我在这里 对 "woshimima"这个字符串进行了五次加密盐操作,输出的值每次都不一样。

        for (int i = 0; i < 5; i++) {
            String woshimima = this.encrypt("woshimima");
            System.out.println(woshimima);
        }

在这里插入图片描述

2c07fb2d8a8c480e9e028d3f877484d1#b188f278a2274491401a0dc98b900fb4
f5299668dc9947818bcdbe0e758e8e31#090582f9c286319ddb563da2a7a3ee48
15fc5201bccb4088975f9acf0f6ccfca#7e293be19e4d985cab4cbcf2eddb530c
a9596645403e45cf9cf852268310eb5f#1f686cc11f5ea73b87ac0de68b7527d5
7817e5dfc0c44aa3b94fe835717aef43#3c6e228769d8809477ba741f954e8ee0

无论拿哪一个去验证都会是正确

在这里插入图片描述

2.2 使用spring security 的密码加盐算法

2.2.1 引入依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

2.2.2 测试

在启动类上加入(exclude = SecurityAutoC onfiguration.class) 关闭注册登录的验证

@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
public class AdminApplication {

	public static void main(String[] args) {
		SpringApplication.run(MeduAdminApplication.class, args);
	}

}

单元测试:

@Test
    void contextLoads() {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String str = "123456";
        //进行加密
        String finalPassword = bCryptPasswordEncoder.encode(str);
        System.out.println(finalPassword);
        //验证密码
        String inputPassword1 = "123456";
        String inputPassword2 = "666666";
        //inputPassword是用户输入的密码(待验证),finalPassword是存储在数据库中的最终密码格式
        System.out.println(bCryptPasswordEncoder.matches(inputPassword1,finalPassword));
        System.out.println(bCryptPasswordEncoder.matches(inputPassword2,finalPassword));
    }

在这里插入图片描述

3 写在最后

使用加密盐的方式,泄露加密后的密码也是大不了的事,根本破解不了,即使是123456也展现为 无数种字符串形式

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值