BCrypt加密算法的使用及原理

BCrypt加密算法的使用及原理在我们开发过程中肯定会对于一些保密数据进行加密存储 加密的方式有很多 例如大家常见的 MD5 SHA 256 等加密方法

大家好,欢迎来到IT知识分享网。

系列文章目录

1.SpringBoot整合RabbitMQ并实现消息发送与接收
2. 解析JSON格式参数 & 修改对象的key
3. VUE整合Echarts实现简单的数据可视化
4. List<HashMap<String,String>>实现自定义字符串排序(key排序、Value排序)
5. 使用JAVA代码实现生成二维码

更多文章可看我主页哦~



前言

    在我们开发过程中肯定会对于一些保密数据进行加密存储,加密的方式有很多,例如大家常见的MD5、SHA-256等加密方法。这边我以前使用的是MD5,主要是因为MD5容易被解密。因为MD5在值相同时,加密出的内容都是相同的。这样对于数据很容易就会被激活成功教程,怎样能做到相同值在加密后的值不相同呢?
    引入我们今天的主角BCrypt算法,BCrypt算法是一种用于密码散列的加密算法,设计用于安全地处理用户密码。它结合了散列算法和盐的使用,具有较高的安全性抗激活成功教程能力
    下面带大家了解BCrypt算法具体的使用方法以及一些原理的解析,让大家能够清晰的明白该算法的用途以及解决大家心中的疑惑~


一、加密原理及代码

1.1 原理

    相信大家在看这篇文章时也是见过BCrypt算法加密后的字符串样子,但对于里面的内容以及为什么会生成这样的字符串还不太明白,先来看下图:
在这里插入图片描述
上图中就是BCrypt算法生成字符串的结构组成,由四个部分组成:

  • 算法标识符 (2a):这个前缀表示使用了Bcrypt算法。 2 a 2a 2a是Bcrypt的一个版本标识符。
  • 代价因子 (10):代价因子表示算法的复杂度,也就是加密过程中迭代的次数。10表示算法使用2的10次方,即1024轮处理。这决定了计算哈希所需的时间和资源量。
  • 盐(Salt) :盐是一个16字节(128位)的随机值,用于增加哈希的唯一性和安全性。它经过Base64编码后变成22个字符的字符串。
  • 哈希值 (Hash):这是经过Bcrypt算法处理后的哈希值。它是24字节(192位)的原始哈希值,经过Base64编码后变成31个字符的字符串。

1.2 代码

    下面我们来使用代码生成字符串,因为相同值生成的密文是不同的,所以这里代码也做比较。是具体代码如下:

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; public class test { 
    // 创建 BCryptPasswordEncoder 实例 private static final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); / * 加密密码 * * @param rawPassword 明文密码 * @return 加密后的密码 */ public static String encryptPassword(String rawPassword) { 
    return passwordEncoder.encode(rawPassword); } public static void main(String[] args) { 
    String password = ""; String encryptedPassword = encryptPassword(password); String encryptedPassword1 = encryptPassword(password); // 比对加密后的密码 boolean isMatch = passwordEncoder.matches(password, encryptedPassword); boolean isMatch1 = passwordEncoder.matches(password, encryptedPassword1); System.out.println("Encrypted Password: " + encryptedPassword); System.out.println("Encrypted Password1: " + encryptedPassword1); System.out.println("Passwords match: " + isMatch); System.out.println("Passwords match1: " + isMatch1); } } 

注:导入包security权限包,需要引入依赖。

1.3 运行效果

    从效果图可以看到,同样是进行原密码:的加密,加密的结果是不一样的。但是在通过原密码和加密后的密码对于时,都可以返回true。表名都是密码加密的。如下图所示:
在这里插入图片描述
这里大家可能会有2个疑问

  1. 为什么相同参数在加密时会生成不同的密文?
  2. 密文都不同了,怎么去和原密码进行的比较能得出结果呢?(即2个不同的密文,都和原文比较得出相同的结果)

二、原理

2.1 密文随机生成

  • 盐的使用:BCrypt 在加密过程中会生成一个独特的盐,并将其与密码进行混合。每次加密时,盐都会不同,因此即使原始密码相同,每次加密生成的加密值也会不同。
  • 加密过程:BCrypt 的加密过程包括盐的生成和散列计算。由于盐是随机的,生成的散列值会有所不同。即使输入相同,但由于每次使用不同的盐,输出也会不同。

    上述加密字符串的结构是由四部分组成的,其中包含盐。这里BCrypt自动生成一个随机盐值,盐的目的是防止相同密码生成相同的散列值。也正因为如此,hash值也会发现不一样。所以我们看到的加密字符串的内容是不一样的。

2.2 passwordEncoder.matches 方法比较结果为什么都为true?

注:passwordEncoder.matches 方法在比较密码时并不是直接比较加密后的值,而是执行以下步骤:

  • 提取盐:从加密后的值中提取盐。
  • 重新加密:使用提取出的盐和提供的密码重新计算加密值。
  • 比较:将重新计算的加密值与存储的加密值进行比较。

因为提取的是加密字符串中的盐,所以在传入的原密码使用提取的盐进行加密,得到的密文肯定是和一致的相同的盐散列值(hash)一样。所以会返回true,

大家在这里应该会比较清楚的知道输出效果图中的含义了。但是我来问大家一个问题:它是怎么提取加密后值中的盐呢?

2.3 如何提取加密后值中的盐

    这个其实第一张图认识字符串的组成结构时介绍了生成的规则。那么生成的规则也将是用来提取盐的重要部分:

  1. 首先底层会将加密的值进行拆分成四部分。
  2. 获取到盐的22个字符的字符串
  3. 因为这个字符串是BASE64加密后的,我们解码后也可以拿到一个16字节(128位)的随机值。

2.4 提取盐之后,如何进行的比较

  1. 使用提取出的盐原密码生成新的哈希值。此时原密码是必须的,因为新的哈希值是基于原密码和盐计算出来的。
  2. 将生成的哈希值与存储的哈希值进行比较。这一步确保了输入密码的正确性。

注:这里是重点,matches 方法比较原密码和加密是否一直时,是通过哈希值(也就是散列值)进行的比较。因为算法标识符 (2a)、代价因子(10)是固定的,盐的话也是通过密文去生成的,所以肯定一致。可能出现不一样的地方只有哈希值(因为哈希值的生成是通过提取出的盐和原密码生成的)

三、如何运用

  1. 首先用户表密码字段需存入BCrypt算法加密的密文(这里在用户注册时,可通过下述代码生成密文)。
public static String encryptPassword(String rawPassword) { 
    return passwordEncoder.encode(rawPassword); } 
  1. 在用户登录时,通过用户名查询表,获取对应的实体。然后拿到实体中的密码作为matches(password, encryptedPassword);方法中的encryptedPassword参数,password就是用户输入的参数值。
  2. 调用matches方法查看返回值,如果返回true,则用户名和密码正确。否则返回“用户名或密码错误”。

这里简写一个实现代码,来体现步骤二、三。具体如下所示:

@PostMapping("/login") public R<User> login( @RequestBody User user){ 
    //1.将页面提交的密码 String password=user.getPassword(); //2.根据页面提交的用户名username查询数据库 LambdaQueryWrapper<User> queryWrapper=new LambdaQueryWrapper<>(); queryWrapper.eq(User::getUsername,user.getUsername()); User selectuser = userService.getOne(queryWrapper); // 比对加密后的密码 boolean isMatch = passwordEncoder.matches(password, selectuser.getPassword()); if(!isMatch){ 
    return R.error("用户名或密码不正确"); } //封装token Map<String,Object> map=new HashMap<>(); // map.put("token",token); return R.success(newUser,map); } 

当然,这只是一个常规的场景需要用到对数据的加密。正常情况下对于表中的关键数据大多数都应该进行加密处理,例如用户的身份证号等重要信息值。这样即使是数据库数据泄露,也不会造成太大的影响,加密的数据很安全。

四、为什么要用BCrypt算法进行加密

    Bcrypt算法是一个密码哈希算法,它的好处有很多,专门设计用于保护密码存储,其主要优点包括:

  • 抗暴力激活成功教程:Bcrypt使用自适应的计算复杂度(代价因子),使得随着计算能力的提升,算法仍然能够保持其激活成功教程难度。这种自适应性增加了暴力激活成功教程的难度。
  • 内置盐:Bcrypt自动生成盐,并将其与哈希值一起存储。盐的使用防止了相同密码的哈希值重复,增强了安全性。
  • 抗彩虹表攻击:由于每个密码都包含独特的盐,即使两个用户使用相同的密码,哈希值也会不同。这使得预计算的彩虹表攻击变得不切实际。
  • 自适应性:代价因子(工作因子)可以调整,允许增加计算复杂度以抵御不断提高的计算能力。这使得Bcrypt能够应对未来的硬件进步。
  • 稳定性和可靠性:Bcrypt算法经过广泛使用和测试,被认为是一个成熟、可靠的密码哈希算法。
  • 防止硬件加速攻击:Bcrypt的设计旨在避免硬件加速攻击(例如GPU、FPGA等),因为它需要大量的计算资源,而不是简单的并行处理。

总结

    相信大家通读完全文后也对于BCrypt算法有了一定的理解。希望大家在日后的学习或者工作中能够运用到,对于数据的安全性是有很大帮助的。
    我在自己学习时也是遇到了很多的问题,本想着加密算法,没打算写文章的。但是在网上搜索时发现了很多文章介绍的不够全面,有些细节点在读完之后还是很疑惑。导致我在学习的过程中耗费了不少的时间成本。为了让大家的学习成本降低,所以写了这篇文章。希望大家能够通过这篇文章去理解和会去使用BCrypt加密算法~
    如果有什么问题都可以留言或者私信我哦~ 也希望大家有更多见解的朋友能够下方留言,让更多的人对BCrypt算法的知识点体会更加深刻~

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/116478.html

(0)
上一篇 2024-11-19 07:26
下一篇 2024-11-19 07:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信