密码加密及验证

目录

为什么需要加密?

密码算法分类

对称密码算法

非对称密码算法

摘要算法

DigestUtils

MD5在线解密工具原理

实现用户密码加密

代码实现


为什么需要加密?

  在MySQL数据库中,我们常常需要对用户密码、身份证号、手机号码等敏感信息进行加密,以保证数据的安全性。若我们直接使用明文存储这些敏感信息,当黑客入侵数据库时,就可以轻松拿到用户的相关信息,从而造成信息泄露或财产损失

密码算法分类

密码算法主要分为三类:对称密码算法、非对称密码算法和摘要算法

对称密码算法

对称密码算法:对称密码算法使用相同的密钥来进行加密和解密。这意味着在加密和解密过程中都使用相同的密钥。对称密码算法通常比非对称密码算法更快速,因为它们不涉及复杂的数学运算。

我们可以将加密的过程看做数学中计算 y = f(x) 的过程,其中 x 为明文,y 为密文,f( )表示不同的加密算法,通过 f(x) 计算密文y

对于对称加密,由于其在加密和解密过程中使用相同的密钥,即

计算密文:y = f(x)

计算明文:x = f(y)

对称密码算法可以进一步分为两种类型:块密码和流密码

块密码:块密码将明文划分为固定大小的块,并对每个块进行加密。常见的块密码算法有:

DES(Data Encryption Standard):DES是一种早期的对称加密算法,使用56位密钥和64位分组大小。

3DES(Triple DES):3DES是对DES的改进,使用两次或三次DES加密过程来增加密钥长度和安全性。它使用的密钥长度为56位,但由于密钥被使用多次,实际的密钥长度为112位或168位。

AES(Advanced Encryption Standard):AES是目前广泛使用的对称加密算法,其密钥长度可以是128位、192位或256位。AES具有较高的安全性和性能,被广泛应用于各种加密场景。

流密码:流密码将明文与密钥流进行按位异或运算来进行加密。密钥流可以是伪随机生成的,也可以是基于密钥和其他参数的确定性生成的。常见的流密码算法有:

RC4(Rivest Cipher 4):RC4是一种流密码算法,曾经被广泛用于加密通信协议中,如WEP和SSL/TLS。

Salsa20ChaCha20:Salsa20和ChaCha20是由丹尼尔·J·伯恩斯坦(Daniel J. Bernstein)设计的流密码算法,被广泛认为是高性能和安全的加密算法,被用于加密通信和随机数生成等领域。

非对称密码算法

非对称密码算法:非对称密码算法使用一对密钥,即公钥和私钥,来进行加密和解密。这意味着使用公钥对数据进行加密后,只有持有相应私钥的实体才能解密数据。非对称密码算法也被称为公钥密码算法,相对于对称密码算法来说,它提供了更好的密钥管理和安全性。

同样的,我们将加密的过程看做数学中计算 y = f(x) 的过程

而对于非对称加密,其使用用户公钥进行加密,私钥进行解密,即

计算密文:y = f(x)

计算明文:x = m(y)

其中 x 为明文,y 为密文,f( )表示加密算法(也可看做公钥),通过 f(x) 计算密文y;m( )表示解密算法(也可看做私钥),通过m(y)计算明文

常见的非对称密码算法有:

RSA(Rivest-Shamir-Adleman):RSA是一种基于大整数的非对称加密算法,广泛应用于安全通信、数字签名等领域。RSA算法的安全性基于大整数分解的困难性,即在已知公钥的情况下,无法有效地分解出私钥。

DSA(Digital Signature Algorithm):DSA是一种用于数字签名的非对称加密算法,主要用于确保数字信息的完整性和真实性。DSA算法与SHA-1或SHA-2哈希函数结合使用,以生成数字签名。

ECC(Elliptic Curve Cryptography):ECC是一种基于椭圆曲线离散对数问题的加密算法,它提供了与RSA相当的安全性,但使用更短的密钥长度,从而降低了计算和存储成本。

摘要算法

摘要算法:摘要算法也称为哈希函数,是一种将任意长度的输入消息转换为固定长度的输出值(哈希值)的算法。

同样的,我们将加密的过程看做数学中计算 y = f(x) 的过程,其中 x 为明文,y 为密文,f( )表示加密算法

对于摘要算法,可以通过y = f(x)计算密文,而无法通过密文计算明文

摘要算法具有以下特性:

固定长度输出:摘要算法生成的哈希值长度是固定的,不受输入消息长度的影响。

唯一性:对于不同的输入消息,摘要算法应该生成不同的哈希值。理想情况下,不同的输入应该产生唯一的哈希值,但由于输出空间有限,可能存在碰撞(多个不同的输入生成相同的哈希值)。

不可逆性:从哈希值推导原始输入消息应该是困难的,即使在已知哈希值的情况下,也应该难以确定原始输入消息。

抗碰撞性:摘要算法应该具有良好的抗碰撞性,即在计算上难以找到两个不同的输入消息产生相同的哈希值。

常见的摘要算法有:

MD5(Message Digest Algorithm 5):是一种广泛使用的哈希函数,用于产生128位(16字节)的哈希值。MD5算法主要用于对消息进行一致性校验、数据完整性验证等非加密目的。

SHA-1(Secure Hash Algorithm 1):SHA-1是一种被广泛使用的摘要算法,但由于其存在碰撞攻击,逐渐被淘汰。

SHA-256、SHA-384、SHA-512:这些是SHA-2家族的一部分,它们分别生成256位、384位和512位长度的哈希值。SHA-2算法提供了更高的安全性,被广泛应用于各种加密应用中。

SHA-3(Secure Hash Algorithm 3):SHA-3是NIST选出的新一代哈希算法标准,其设计目标是提供与SHA-2不同的算法选择,以增加算法多样性。

DigestUtils

DigestUtils 是Spring为我们提供的一个MD5加密工具类,用于生成MD5哈希值,进行消息摘要的计算,我们可以直接利用该工具类中的方法来对数据进行加密

其中,常用的方法有:

byte[] md5Digest(byte[] bytes):计算给定字节数组的MD5哈希值

byte[] md5Digest(InputStream inputStream):计算给定输入流的MD5哈希值

String md5DigestAsHex(byte[] bytes):计算给定字节数组的MD5哈希值,并以十六进制字符串形式返回结果

String md5DigestAsHex(InputStream inputStream):计算给定输入流的MD5哈希值,并以十六进制字符串形式返回结果

StringBuilder appendMd5DigestAsHex(byte[] bytes, StringBuilder builder):计算给定字节数组的MD5哈希值,并将其以十六进制字符串形式添加到给定的StringBuilder

StringBuilder appendMd5DigestAsHex(InputStream inputStream, StringBuilder builder):计算给定输入流的MD5哈希值,并将其以十六进制字符串形式添加到给定的StringBuilder

 我们以对用户密码进行加密为例,来进一步学习DigestUtils:

import org.springframework.util.DigestUtils;

public class MD5UtilsTest {
    public static void main(String[] args) {
        String password1 = DigestUtils.md5DigestAsHex("123456".getBytes());
        System.out.println("123456: " + password1);
        String password2 = DigestUtils.md5DigestAsHex("123456".getBytes());
        System.out.println("123456: " + password2);
        String password3 = DigestUtils.md5DigestAsHex("123457".getBytes());
        System.out.println("123457: " + password3);
        String password4 = DigestUtils.md5DigestAsHex("12345".getBytes());
        System.out.println("12345:  " + password4);
    }
}

运行结果:

我们可以看到:对于相同的输入生成相同的哈希值,而不同的输入生成不同的哈希值,且 “123456” 和 “123457” 只有一个字符不相同,但生成的哈希值差别却很大,生成的哈希值长度是固定的,不受输入消息长度的影响

MD5在线解密工具原理

MD5是一种摘要算法,摘要算法具有不可逆性,那么网上的MD5在线解密工具是如何解密的呢?

  这是因为其会将常用的字符串的MD5哈希值保存到数据库中,当用户输入一个MD5哈希值时,就会尝试找到对应的明文,若找到对应的哈希值与明文的映射,则返回该明文作为解密结果;若没有找到对应映射,则可能会放弃解密(这是因为实时计算MD5哈希值对应的明文需要消耗大量的计算资源,尤其是对应复杂的密码或长文本)

我们随便找一个在线解密工具网站:

输入之前 “123456”的哈希值进行解密:

对应较为简单的 123456,则很快得出结果

而当我们输入较为复杂的明文进行加密:

此时再尝试进行解密:

则会解密失败

实现用户密码加密

我们通过MD5算法对用户密码进行加密,但由于其不可逆性,我们该如何进行判断用户输入的密码是否正确呢

虽然经过MD5加密后的密文无法解密,但由于相同的密码经过MD5哈希后得到的密文是相同的,我们可以利用这个特性对密码进行验证

计算用户输入的密码的哈希值,并将其与数据库中存储的哈希值相比较,若相同,则用户输入的密码正确;若不同,则用户输入的密码错误

即,采用 判断哈希值是否一致 的方法来判断密码是否正确

但是,正是由于相同的密码经过MD5哈希后的密文是相同的,当存储用户密码的数据库泄露后,攻击者很容易找到相同密码的用户,从而降低了破解密码的难度,且用户输入的密码可能为弱密码(如 123456、666666等),此时破解密码的难度也较低。

因此,我们在对用户密码进行加密时,需要考虑对密码进行包装,即使是相同的密码,也保存为不同的密文,即用户即使是输入的弱密码,也对其进行增强,从而增加密码被攻破的难度

那么应该如何实现呢?

我们可以为密码拼接一个复杂字符后进行加密,为了进一步提供安全性,我们可以拼接一个随机复杂字符串,这个随机复杂字符串我们称之为 “盐”

这样,当黑客通过一定手段拿到这个加密串时,拿到明文并不是我们加密前的字符串,而是加密前的字符串和盐组合的字符串,这样相对来说又增加了字符串的安全性

因此,用户密码加密实现为:

如何生成随机盐值呢?

我们可以使用 UUID 生成随机盐值

UUID(Universally Unique Identifier)是一种标准化的格式,用于表示全局唯一的标识符。UUID通常以32位的十六进制数字表示,由五段组成,以连字符分隔,例如:550e8400-e29b-41d4-a716-446655440000

我们可以通过randomUUID()方法来生成唯一识别码:

import java.util.UUID;

public class MD5UtilsTest {
    public static void main(String[] args) {
        System.out.println(UUID.randomUUID());
        System.out.println(UUID.randomUUID());
        System.out.println(UUID.randomUUID());
    }
}

运行结果:

我们可以将其结果转换为字符串,并去掉其中的 “-”

import java.util.UUID;

public class MD5UtilsTest {
    public static void main(String[] args) {
        System.out.println(UUID.randomUUID().toString().replace("-", ""));
    }
}

此时,我们就可以得到 32位 随机盐值:

此时,我们将密码和随机盐值一起进行MD5哈希:

import org.springframework.util.DigestUtils;
import java.util.UUID;

public class MD5UtilsTest {
    public static void main(String[] args) {
        String password1 = DigestUtils.md5DigestAsHex(("123456" + UUID.randomUUID().toString().replace("-", "")).getBytes());
        System.out.println("123456: " + password1);
        String password2 = DigestUtils.md5DigestAsHex(("123456" + UUID.randomUUID().toString().replace("-", "")).getBytes());
        System.out.println("123456: " + password2);
    }
}

运行结果:

此时,即使是相同的密码,加密后生成的哈希值也是不同的

由于我们通过 判断哈希值是否一致 的方法来判断密码是否正确,因此在用户登录输入密码时,我们需要拿到 用户注册时生成的随机盐值,因此我们需要在数据库中存储 盐值 和 密文,(即 盐值 + MD5(明文 + 盐值))

在存储盐值和密文时,我们可以存储:

盐值 + 密文

密文 + 盐值

4位盐值 + 4位密文 + 4位盐值 + 4位密文 + ...

4位密文+ 4位盐值 + 4位密文 + 4位盐值 + ...

......

 有多种存储方式,同样,我们在拼接明文和盐值时也有多种拼接方式

在学习了如何实现用户密码加密后,我们来通过代码实现 加密 和 验证

代码实现

我们首先来实现加密:

1. 生成随机盐值

2. 对 明文 + 随机盐值进行MD5加密

    /**
     * 对用户注册密码进行加密
     * @param password 用户注册密码
     * @return 数据库中存储信息(盐值 + 密文)
     */
    public static String encipher(String password) {
        // 生成盐值
        String salt = UUID.randomUUID().toString().replace("-", "");
        //将盐值 + 明文进行加密
        String secretPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
        return salt + secretPassword;
    }

接下来,我们实现验证:

1. 校验输入的密码是否有效

2. 校验数据库中存储的密码是否有效

3. 获取盐值

4. 根据用户登录输入的密码和盐值进行加密,生成哈希值

5. 比较生成的哈希值和数据库中存储的密文是否相同

    /**
     * 验证密码是否正确
     * @param inputPassword 用户登录时输入的密码
     * @param sqlPassword 数据库中存储的密码(盐值 + 密文)
     * @return 密码是否正确
     */

    public static Boolean verify(String inputPassword, String sqlPassword) {
        //校验
        if(!StringUtils.hasLength(inputPassword)) {
            return false;
        }
        if(!StringUtils.hasLength(sqlPassword) || sqlPassword.length() != 64) {
            return false;
        }
        // 解析盐值
        String salt = sqlPassword.substring(0, 32);
        // 生成哈希值
        String secretPassword = DigestUtils.md5DigestAsHex((salt + inputPassword).getBytes());
        //判断是否相同
        return sqlPassword.equals(salt + secretPassword);
    }

 除了使用 MD5进行加密,我们也可以使用 AES、RSA等加密算法或自己实现加密算法进行加密

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

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

相关文章

pod 控制器介绍

一 pod 控制器相关理论介绍 1,Pod控制器 是什么 Pod控制器,又称之为工作负载(workload),是用于实现管理pod的中间层,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试进行…

使用modbus-serial 库搭配 modbus slave 通过 modbus tcp client 协议来 写入 modbus 寄存器值

使用modbus-serial 库对modbus slave 写入寄存器值 modbus tcp client 代码 目标电脑(启动modbus slave 的电脑)ip为 192.168.3.46,端口502 // 读取另一台电脑,192.168.3.46:502 Modbus TCP // create an empty modbus client c…

2005NOIP普及组真题 4. 循环

线上OJ&#xff1a; 【05NOIP普及组】循环 核心思想&#xff1a;高精度 1、本题用到了标准的高精度乘法模板 void init(int a[]) //传入一个数组 {string s; cin >> s; //读入字符串s a[0] s.length(); //用a[0]计算字符串s的位数 for(i 1; i < a[0]; i) a[i] …

颠覆与重塑|AI助力汽车开发,汽车智能势不可挡

汽车行业深受人工智能的影响&#xff0c;人工智能正在为我们创造全新的出行方式。随着智能化的加速普及&#xff0c;越来越多的消费者开始关注汽车的智能化。智能化的水平已经成为众多消费者购车的参考因素&#xff0c;也成了车企竞争的主赛道&#xff0c;汽车行业也已经成为人…

高校科研信息管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;公告管理&#xff0c;反馈管理&#xff0c;操作日志管理&#xff0c;科研项目管理&#xff0c;通知管理 科研人员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;反馈管理&#xff…

[SQL-SERVER:数据库安全及维护]:MSSM工具对用户进行用户授权和角色授权操作

文章目录 直接为用户授权&#xff08;20分&#xff09;1. 创建登录TLogin&#xff0c;自行指定登录密码服务器层面选择 安全性 > 点击 登录名 > 点击右键 > 点击 新建登录名 > 选择sqlserver验证 > 关闭强制登录更改密码异常解决&#xff1a;sqlserver 配置管理…

【最新鸿蒙应用开发】——什么是应用开发模型?Stage模型

在应用程序开发时通常需要使用应用模型来提供必备的组件和运行机制&#xff0c;有了应用模型&#xff0c;开发者可以基于一套统一的模型进行应用开发&#xff0c;使应用开发更简单、高效。接下来谈谈鸿蒙应用开发当中的两种模型&#xff1a; Stage模型&#xff1a; HarmonyOS …

过滤器、监听器、拦截器的区别

过滤器、监听器、拦截器的区别 过滤器&#xff08;filter&#xff09;、监听器&#xff08;Listener&#xff09;是JavaWeb的三大组件。而拦截器&#xff08;Interceptor&#xff09;是Spring框架中的。 我们主要是要分清除过滤器和拦截器的区别&#xff1a; 实现原理&#…

晶体(二):差分晶振

一、定义 差分晶振是一种有源晶体振荡器&#xff0c;输出差分信号&#xff08;由两个相位相反、幅度相等的信号组成&#xff09;&#xff0c;从而消除了共模噪声&#xff0c;具有抗干扰能力强、对参考电平完整性要求较弱、抑制串扰、EMI 能力强、功耗小、速率高、不受温度和电压…

【Ubuntu常用命令】终端个人常用命令总结

【Ubuntu常用命令】终端常用命令总结 查看硬盘挂载情况查看内存占用情况移动或重命名文件和目录复制文件或目录conda安装本地文件 查看硬盘挂载情况 mount 命令会列出当前系统上所有已挂载的文件系统。它会显示挂载点、文件系统类型、挂载选项等信息 mount df 命令用于显示文…

MySQL学习——影响选项文件处理的命令行选项和程序选项修改器

大多数支持选项文件的MySQL程序都处理以下选项。因为这些选项会影响选项文件的处理&#xff0c;所以必须在命令行上给出&#xff0c;而不是在选项文件中给出。为了正常工作&#xff0c;这些选项中的每一个都必须先于其他选项给出&#xff0c;但以下情况除外&#xff1a; -prin…

AK F.*ing leetcode 流浪计划之费马小定理与组合数取模

欢迎关注更多精彩 关注我&#xff0c;学习常用算法与数据结构&#xff0c;一题多解&#xff0c;降维打击。 费马小定理与证明 参考 https://zhuanlan.zhihu.com/p/594859227 费马小定理&#xff1a;如果p是一个质数&#xff0c;而正整数a不是p的倍数&#xff0c;那么a(p-1)≡…

继承的基本语法

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在编写类时&#xff0c;并不是每次都要从空白开始。当要编写的类和另一个已经存在的类之间存在一定的继承关系时&#xff0c;就可以通过继承来达到代…

AI早班车6.3

1.蚂蚁技术日&#xff1a;支付宝三大「AI 管家」亮相。 2.百度赵世奇&#xff1a;百度搜索&#xff0b;文心智能体平台&#xff0c;助力智能体人人可用。 3.腾讯&#xff1a;发布大模型App腾讯元宝。 4.AFAC2024金融智能创新大赛启动&#xff0c;让高质量金融服务人人可用 …

Docker笔记-解决非交互式运行python时print不输出的问题

换句话来说就是在docker中如何不会python的print 只需要在启动时&#xff0c;不让python缓冲其输出。 关键命令如下&#xff1a;PYTHONUNBUFFERED1 如下&#xff1a; docker run -e PYTHONUNBUFFERED1 <your_image> 下面解释下-e "-e"选项的全称是"…

lux和ffmpeg进行下载各大主流自媒体平台视频

1、lux下载&#xff0c;链接&#xff1a;https://pan.baidu.com/s/1WjGbouL3KFTU6LeqZmACpA?pwdagpp 提取码&#xff1a;agpp 2、ffmpeg下载&#xff0c;跟lux放在同一个目录&#xff1b; 3、为lux、ffmpeg设置环境变量&#xff1b; 4、WINR&#xff0c;打开运行&#xff0…

Love-Yi情侣网站3.0存在SQL注入漏洞

目录 1. 前言 2. 网站简介 3. 寻找特征点 3.1 第一次尝试 3.2 第二次尝试 4.资产搜索 5.漏洞复现 5.1 寻找漏洞点 5.2 进行进一步测试 5.2.1 手动测试 1.寻找字段 2.寻找回显位 3.查询当前用户 5.2.2 sqlmap去跑 6.总结 1. 前言 朋友说自己建了一个情侣网站,看到…

chat4-Server端保存聊天消息到mysql

本文档描述了Server端接收到Client的消息并转发给所有客户端或私发给某个客户端 同时将聊天消息保存到mysql 服务端为当前客户端创建一个线程&#xff0c;此线程接收当前客户端的消息并转发给所有客户端或私发给某个客户端同时将聊天消息保存到mysql 本文档主要总结了将聊天…

基于django | 创建app,并启动django

1、删除系统默认的目录路径&#xff1a;BASE_DIR / templetes 2、在终端输入命令&#xff1a; python manage.py startapp app01 # 这里的app01是我创建app的名称 3、如果没有创建成功&#xff0c;手动点击 Creat App , 4、在 setting.py 中找到 INSTALLED_APPS ,添加 ap…

✅count(1)、count(*) 与 count(列名) 的区别

简单来说&#xff1a; COUNT(1) 和 COUNT(*) 表示的是直接查询符合条件的数据库表的行数。而 COUNT(列名) 表示的是查询符合条件的列的值不为 NULL 的行数。 除了查询得到结果集有区别之外&#xff0c;在性能方面 COUNT() 约等于 COUNT(1)&#xff0c;但是 **COUNT() 是 SQL9…