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也展现为 无数种字符串形式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/803053.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

OSU!题解(概率dp)

题目&#xff1a;OSU! - 洛谷 思路&#xff1a; 设E()表示截止到i所获得的分数&#xff1b; 对于到i点的每一个l&#xff0c;如果第i1点为1&#xff0c;那么会新增分数3*l^23*l1; 就有递推公式方程&#xff1a; E()E()p[i1]p*(3*l^23*l1);(p代表截止到i获得长度l的概率)&a…

关于mybatis中语法的错误记录

大家注意再写mybatis时候的逗号&#xff0c;虽然不起眼&#xff0c;但是会一直报错&#xff0c;最后一个字段不需要逗号&#xff0c;其余字段全部需要逗号。

【个人笔记】685. 冗余连接 II 的解释(并查集)

一棵树有n个点和n条边&#xff0c;返回一条能删除的边&#xff0c;使得剩下的图是有 n 个节点的有根树。 解释&#xff1a; 注意不冗余的有根树的特性&#xff01;**根节点入度为0&#xff0c;其余结点只有一个入度&#xff01;**所以冗余的两种情况如下&#xff1a; &#xff…

Vue3项目基于Axios封装request请求

在 Vue 3 的项目开发中&#xff0c;使用 Axios 进行 HTTP 请求是非常常见的作法&#xff0c;为了更方便开发者更高效的进行代码编写和项目的维护&#xff0c;可以通过再次封装 Axios 来实现。 在本文中&#xff0c;博主将详细指导你如何在自己的 Vue 3 项目中使用 Axios 二次封…

Vue学习---vue cli 项目创建

使用的编辑工具webStorm 创建例子: hello vue create hello 选择 vue3 进行创建 运行 npm run serve 测试访问&#xff1a;http://localhost:8080 改动内容重新编译&#xff1a; npm run build dist 目录就是编译后的可运行内容

客流统计系统优化景区服务流程,增强游客满意度

在当今旅游业蓬勃发展的时代&#xff0c;景区面临着越来越多的挑战和机遇。如何提供更优质、更高效的服务&#xff0c;满足游客日益增长的需求&#xff0c;成为了景区管理者们关注的焦点。客流统计系统作为一种创新的技术手段&#xff0c;正逐渐成为优化景区服务流程、增强游客…

windows 打包pyd文件

1.新建一个py文件&#xff0c;myunit.py&#xff0c;里面的代码是: class Adder: def __init__(self, a, b): self.a a self.b b def add(self): return self.a self.b 2.新建一个py文件&#xff0c;setup.py&#xff0c;里面的代码是: from setuptools import setup fro…

巧用通义灵码助力护网面试

前言 前几年护网还算是一个比较敏感的话题&#xff0c;但是随着近段时间的常态化开始&#xff0c;护网行动也是逐渐走进了大众的视野&#xff0c;成为了社会各界共同关注的安全盛事。本篇也是受通义灵码备战求职季活动的启发&#xff0c;结合近期要开始的护网行动&#xff0c…

持续集成06--Jenkins构建触发器

前言 在持续集成&#xff08;CI&#xff09;的实践中&#xff0c;构建触发器是自动化流程中不可或缺的一环。它决定了何时启动构建过程&#xff0c;从而确保代码变更能够及时地得到验证和反馈。Jenkins&#xff0c;作为业界领先的CI/CD工具&#xff0c;提供了多种构建触发器选项…

2.I/O口

I/O输出(点灯) 分析电路 看电路图&#xff0c;元器件形成电压差&#xff0c;即可点亮LED灯 代码编写 使用不同操作进行LED控制 #include "reg52.h" //51单片机头文件 #include <intrins.h> sbit LED1 P1^0; //引脚初始化&#xff1a;P1^0&#xff1a;对应引脚…

RocketMQ~架构与工作流程了解

简介 RocketMQ 具有高性能、高可靠、高实时、分布式 的特点。它是一个采用 Java 语言开发的分布式的消息系统&#xff0c;由阿里巴巴团队开发&#xff0c;在 2016 年底贡献给 Apache&#xff0c;成为了 Apache 的一个顶级项目。 在阿里内部&#xff0c;RocketMQ 很好地服务了集…

字符串类中的常用方法

1 string对象的创建 静态创建 String s1  "abc";  String s2  "abc";  动态创建 String s3  new String("abc"); String s4  new String("abc"); 2string对象的不可变性 任何一个String对象在创建之后都不能对它的…

甲方建设项目的数智化管理

在军工、石化、电力、民航、食品等大型集团企业和政府机构中&#xff0c;基建、IT、技改等各类固定投资项目属于甲方建设型项目。这类项目无论是EPC总包还是按合同分包&#xff0c;都具有业主型、项目干系人多、跨组织协作频繁、全生命周期管理复杂等特点。如何高效地管理这些甲…

基于LAMMPS模拟岩石表面润湿性

润湿性是指不相混的两相流体与岩石固相表面接触时&#xff0c;其中一相流体沿着岩石表面铺开的现象&#xff0c;该相称为润湿相。润湿性一般采用接触角法来确定&#xff0c;通常根据水在固体表面的角度θ来定义系统的润湿性&#xff0c;接触角为0&#xff5e;75为水润湿&#x…

gihub导入gitee仓库实现仓库同步

昨天在GitHub里导入了gitee仓库&#xff0c;但是在仓库同步这里卡了很久&#xff0c;因为网上大多数都是从github导入gitee&#xff0c;然后github生成token放入实现同步&#xff0c;但是我找到一种更为方便的&#xff01; 1.首先找到项目文件下的.git文件里的config文件 2.在…

C++ | Leetcode C++题解之第238题除自身以外数组的乘积

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<int> productExceptSelf(vector<int>& nums) {int length nums.size();// L 和 R 分别表示左右两侧的乘积列表vector<int> L(length, 0), R(length, 0);vector<int> answer(l…

求解答word图标变白

把WPS卸载了之后就变成白色了&#xff0c;然后在注册表中把word的地址改成office word的地址之后图标变成这样了&#xff0c;怎么办

在国产芯片上实现YOLOv5/v8图像AI识别-专栏目录及必备知识点及相关设备

本专栏主要是提供一种国产化图像识别的解决方案&#xff0c;专栏中实现了YOLOv5/v8在国产化芯片上的使用部署&#xff0c;并可以实现网页端实时查看。根据自己的具体需求可以直接产品化部署使用。 学习本专栏内容需要准备以下硬件设备&#xff1a; 1、RK3588开发板 2、带有 显…

《藏语翻译通》App功能升级,支持藏文词典在线查单词!iPhone用户推荐使用的藏语学习工具!

《藏语翻译通》App上线了藏文词典查单词功能&#xff0c;该功能可以帮助你更有效地学习藏语&#xff0c;以及掌握工作中涉及到的专业术语。本次更新提供了藏汉词典、藏汉大词典、新术语在线查单词功能。 打开App Store搜索关键词&#xff1a;藏文词典 下载这个官方软件 点击首…

leetcode94. 二叉树的中序遍历,递归法+迭代法。附带前序遍历方法

leetcode94. 二叉树的中序遍历 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2] 示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[] 示例 3&#xff1a; …