工作实战之密码防重放攻击

news2024/11/6 3:13:59

目录

前言

一、登录认证密码加密

二、bcrypt加密密码不一样,匹配原理

1.程序运行现象

 2.原理解释

三、密码防重放

总结


前言

密码重放攻击:请求被攻击者获取,并重新发送给认证服务器,从而达到认证通过的目的


一、登录认证密码加密

Spring Security 中内置的加密算法BCrypt,号称最安全的加密算法,除了加盐来抵御rainbow table 攻击之外,bcrypt的一个非常重要的特征就是自适应性,可以保证加密的速度在一个特定的范围内,即使计算机的运算能力非常高,可以通过增加迭代次数的方式,使得加密速度变慢,从而可以抵御暴力搜索攻击。Bcrypt可以简单理解为它内部自己实现了随机加盐处理。使用Bcrypt,每次加密后的密文是不一样的

public interface PasswordEncoder {
   String encode(CharSequence rawPassword);
 
   boolean matches(CharSequence rawPassword, String encodedPassword);
 
   default boolean upgradeEncoding(String encodedPassword) {
      return false;
   }
}

encode:方法接受的参数是原始密码字符串,返回值是经过加密之后的hash值,hash值是不能被逆向解密的。这个方法通常在为系统添加用户,或者用户注册的时候使用。
matches:方法是用来校验用户输入密码rawPassword,和加密后的hash值encodedPassword是否匹配。如果能够匹配返回true,表示用户输入的密码rawPassword是正确的,反之返回fasle。也就是说虽然这个hash值不能被逆向解密,但是可以判断是否和原始密码匹配。这个方法通常在用户登录的时候进行用户输入密码的正确性校验。
upgradeEncoding:设计的用意是,判断当前的密码是否需要升级。也就是是否需要重新加密?需要的话返回true,不需要的话返回fasle。默认实现是返回false。

二、bcrypt加密密码不一样,匹配原理

1.程序运行现象

 public static void main(String[] args) {
        String passworld = "12345";

        PasswordEncoder passwordEncoder = new CustomBCryptPasswordEncoder();
        String encodePasswordOne = passwordEncoder.encode(passworld);
        System.out.println("encodePasswordOne:"+encodePasswordOne);

        String encodePasswordTow = passwordEncoder.encode(passworld);
        System.out.println("encodePasswordTow:"+encodePasswordTow);

        boolean matchesOne = passwordEncoder.matches(passworld,encodePasswordOne);
        System.out.println("matchesOne:"+matchesOne);

        boolean matchesTow = passwordEncoder.matches(passworld,encodePasswordTow);
        System.out.println("matchesTow:"+matchesTow);

    }

 2.原理解释

a.Bcrypt就是一款加密工具,可以比较方便地实现数据的加密工作。你也可以简单理解为它内部自己实现了随机加盐处理。例如,我们使用MD5加密,每次加密后的密文其实都是一样的,这样就方便了MD5通过大数据的方式进行破解。Bcrypt生成的密文是60位的。而MD5的是32位的。使用BCrypt 主要是能实现每次加密的值都是不一样的

b.源码分析

   1) 加密方法,获取了随机盐放入BCrypt.hashpw加密方法中

	public String encode(CharSequence rawPassword) {
		if (rawPassword == null) {
			throw new IllegalArgumentException("rawPassword cannot be null");
		}
		String salt = getSalt();
		return BCrypt.hashpw(rawPassword.toString(), salt);
	}

private String getSalt() {
		if (this.random != null) {
			return BCrypt.gensalt(this.version.getVersion(), this.strength, this.random);
		}
		return BCrypt.gensalt(this.version.getVersion(), this.strength);
	}

2) 匹配方法matches->checkpw->hashpw,hashpw方法把加密后的秘钥放入了随机盐的为止,这个方法里面从密文里面获取了加密时的随机盐real_salt = salt.substring(off + 3, off + 25);从而对新的密码用这个随机盐再加密,进行匹配

public boolean matches(CharSequence rawPassword, String encodedPassword) {
		if (rawPassword == null) {
			throw new IllegalArgumentException("rawPassword cannot be null");
		}
		if (encodedPassword == null || encodedPassword.length() == 0) {
			this.logger.warn("Empty encoded password");
			return false;
		}
		if (!this.BCRYPT_PATTERN.matcher(encodedPassword).matches()) {
			this.logger.warn("Encoded password does not look like BCrypt");
			return false;
		}
		return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
	}


public static boolean checkpw(String plaintext, String hashed) {
		return equalsNoEarlyReturn(hashed, hashpw(plaintext, hashed));
	}
public static String hashpw(byte passwordb[], String salt) {
		BCrypt B;
		String real_salt;
		byte saltb[], hashed[];
		char minor = (char) 0;
		int rounds, off;
		StringBuilder rs = new StringBuilder();

		if (salt == null) {
			throw new IllegalArgumentException("salt cannot be null");
		}

		int saltLength = salt.length();

		if (saltLength < 28) {
			throw new IllegalArgumentException("Invalid salt");
		}

		if (salt.charAt(0) != '$' || salt.charAt(1) != '2') {
			throw new IllegalArgumentException("Invalid salt version");
		}
		if (salt.charAt(2) == '$') {
			off = 3;
		}
		else {
			minor = salt.charAt(2);
			if ((minor != 'a' && minor != 'x' && minor != 'y' && minor != 'b') || salt.charAt(3) != '$') {
				throw new IllegalArgumentException("Invalid salt revision");
			}
			off = 4;
		}

		// Extract number of rounds
		if (salt.charAt(off + 2) > '$') {
			throw new IllegalArgumentException("Missing salt rounds");
		}

		if (off == 4 && saltLength < 29) {
			throw new IllegalArgumentException("Invalid salt");
		}
		rounds = Integer.parseInt(salt.substring(off, off + 2));

		real_salt = salt.substring(off + 3, off + 25);
		saltb = decode_base64(real_salt, BCRYPT_SALT_LEN);

		if (minor >= 'a') {
			passwordb = Arrays.copyOf(passwordb, passwordb.length + 1);
		}

		B = new BCrypt();
		hashed = B.crypt_raw(passwordb, saltb, rounds, minor == 'x', minor == 'a' ? 0x10000 : 0);

		rs.append("$2");
		if (minor >= 'a') {
			rs.append(minor);
		}
		rs.append("$");
		if (rounds < 10) {
			rs.append("0");
		}
		rs.append(rounds);
		rs.append("$");
		encode_base64(saltb, saltb.length, rs);
		encode_base64(hashed, bf_crypt_ciphertext.length * 4 - 1, rs);
		return rs.toString();
	}


 

三、密码防重放

1.鉴于每次加密密码都不一样,所以每次前端传过来的密码只能使用一次,我们用redis的setnx功能来实现密码是否被二次使用

/**
     * 检查密码重放
     */
    protected void checkReplayPassword(String ursername, String password) {
        String md5Pass = EncryptionUtils.MD5.encrypt(password);
        boolean absent = loginRecordService.savePassIfAbsent(ursername, md5Pass,
                securityProperties.getLogin().getPassReplayExpire(), TimeUnit.DAYS);

        if (absent) {
            throw new AuthenticationServiceException(LoginExceptions.DUPLICATE_PASSWORD.value());
        }
    }


总结

密码防重放攻击方案较多,上述只是其中一种简单的防重放方案,是建立在每次加密密码不一样的基础之上

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

系列八、SQL优化

一、插入数据 如果我们需要一次性往数据库表中插入多条记录&#xff0c;可以从以下三个方面进行优化。1.1、优化方案一&#xff08;批量插入数据&#xff09; Insert into tb_test values(1,Tom),(2,Cat),(3,Jerry); 1.2、优化方案二&#xff08;手动控制事务&#xff09; s…

CEC2005:星雀优化算法(Nutcracker optimizer algorithm,NOA)求解CEC2005(提供MATLAB代码)

一、星雀优化算法NOA 星雀优化算法(Nutcracker optimizer algorithm,NOA)由Mohamed Abdel-Basset等人于2023年提出&#xff0c;该算法模拟星雀的两种行为&#xff0c;即&#xff1a;在夏秋季节收集并储存食物&#xff0c;在春冬季节搜索食物的存储位置。 星鸦单独或成对活动&…

C语言循环语句do while和嵌套循环语句讲解

C do…while 循环 不像 for 和 while 循环&#xff0c;它们是在循环头部测试循环条件。在 C 语言中&#xff0c;do…while 循环是在循环的尾部检查它的条件。 do…while 循环与 while 循环类似&#xff0c;但是 do…while 循环会确保至少执行一次循环。 语法 C 语言中 do…w…

杂谈:数组index问题和对象key问题

面试题一&#xff1a; var arr [1, 2, 3, 4] 问&#xff1a;arr[1] ?; arr[1] ?答&#xff1a;arr[1] 2; arr[1] 2 这里可以再分为两个问题&#xff1a; 1、数组赋值 var arr [1, 2, 3, 4]arr[1] 10; // 数字场景 arr[10] 1; // 字符串场景 arr[a] 1; // 字符串…

索莫菲模型的一些理解 Smomerfeld Model

如何解释传统热容算出来的数值与量子模型下的区别&#xff1f; 因为只有费米能附近的电子才能够进行移动&#xff0c;这个是问题的差别所在 我们下面就来介绍如何求费米能&#xff08;费米能的计算&#xff09; 既然费米能附近的电子很重要&#xff0c;那么附近的电子有多少很…

语义分割前储知识

CNN中的Layers 除了正向传播计算loss&#xff0c;反向传播更新parameters&#xff0c;我们还需要知道参数是如何计算的&#xff0c;这个很重要。 我们这里介绍几个在deep learning中经常用到的几个层&#xff0c;dense layer&#xff08;全连接层&#xff09;&#xff0c;con…

Redis源码---有序集合为何能同时支持点查询和范围查询

目录 前言 Sorted Set 基本结构 跳表的设计与实现 跳表数据结构 跳表结点查询 跳表结点层数设置 哈希表和跳表的组合使用 前言 有序集合&#xff08;Sorted Set&#xff09;是 Redis 中一种重要的数据类型&#xff0c;它本身是集合类型&#xff0c;同时也可以支持集合中…

记一次Nodejs减低npm版本的踩坑日记

使用了npm install -g npm6.4.1指令之后&#xff0c;把npm版本减低了&#xff0c;让后悲催的就来了。 由于npm 6.4.1 已经过时&#xff0c;导致运行npm时出现 npm does not support Node.js v18.14.2 版本不兼容问题 升级npm版本&#xff0c;npm install -g npmlatest 没用还是…

DM-VIO论文翻译

简介 DM-VIO: Delayed Marginalization Visual-Inertial Odometry DM-VIO: 延迟边缘化惯性视觉里程计 花了两天时间捏着鼻子把这篇论文翻译完了&#xff0c;很多术语和状态的表达方式可能是和这个团队以前的工作DSO以及VI-DSO保持了一致&#xff0c;所以看起来很是费劲&#…

STM32开发(17)----CubeMX配置CRC

CubeMX配置CRC前言一、什么是CRC&#xff1f;二、实验过程1.STM32CubeMX配置2.代码实现重载printf3.实验结果总结前言 本章介绍使用STM32CubeMX对CRC进行配置的方法&#xff0c;CRC的目的是保证数据的完整性&#xff0c;所有的STM32芯片都内置了一个硬件的CRC计算模块&#xf…

指针的进阶【下篇】

文章目录&#x1f4c0;8.指向函数指针数组的指针&#x1f4c0;9.回调函数&#x1f4c0;8.指向函数指针数组的指针 &#x1f330;请看代码与注释&#x1f447; int Add(int x, int y) {return x y; } int Sub(int x, int y) {return x - y; } int main() {int (*pf)(int, int…

T3 出行云原生容器化平台实践

作者&#xff1a;林勇&#xff0c;就职于南京领行科技股份有限公司&#xff0c;担任云原生负责人&#xff0c;也是公司容器化项目的负责人。主要负责 T3 出行云原生生态相关的所有工作&#xff0c;如服务容器化、多 Kubernetes 集群建设、应用混部、降本增效、云原生可观测性基…

2023年中小企业实施智能制造的建议

智能制造的载体是制造系统&#xff0c;制造系统从微观到宏观有不同的层次&#xff0c;主要包括制造装备、制造单元、制造车间&#xff08;工厂&#xff09;、制造企业和企业生态等。随着智能制造的深入推进&#xff0c;未来智能制造将向以下五个方向发展。 &#xff08;一&…

FPGA采集AD7606全网最细讲解 提供串行和并行2套工程源码和技术支持

目录1、前言2、AD7606数据手册解读输入信号采集范围输出模式选择过采样率设置3、AD7606串行输出采集4、AD7606并行输出采集5、vivado仿真6、上板调试验证7、福利&#xff1a;工程代码的获取1、前言 AD7606是一款非常受欢迎的AD芯片&#xff0c;因为他支持8通道同时采集数据&am…

CFT Show 信息收集篇

CFT Show 信息收集篇1.CFT Show 信息收集篇1.1.WEB-11.1.1.打开靶场1.1.2.寻找Flag1.2.WEB-21.2.1.打开靶场1.2.2.寻找Flag1.3.WEB-31.3.1.打开靶场1.3.2.寻找Flag1.3.2.1.F12查看器1.3.2.2.查看源码1.3.2.3.抓包1.4.WEB-41.4.1.打开靶场1.4.2.寻找Flag1.4.2.1.robots介绍1.4.2…

10个黑客基础教程!简单有效

如果你的电脑运行缓慢&#xff0c;请使用下面介绍的方法来帮助加速、优化和提高电脑的性能。 1.关闭启动时自动运行的应用程序 计算机上安装的许多应用程序都可以将自己配置为在启动期间自动启动并继续在后台运行&#xff0c;但是&#xff0c;如果不是每天都使用这些应用程序…

基于vscode创建SpringBoot项目,连接postgresql数据库 2 更简单

1、Vue下载安装步骤的详细教程(亲测有效) 1_水w的博客-CSDN博客 2、Vue下载安装步骤的详细教程(亲测有效) 2 安装与创建默认项目_水w的博客-CSDN博客 3、基于vscode开发vue项目的详细步骤教程_水w的博客-CSDN博客 4、基于vscode开发vue项目的详细步骤教程 2 第三方图标库FontAw…

Spark RDD持久化

RDD Cache缓存 RDD通过Cache或者Persist方法将前面的计算结果缓存&#xff0c;默认情况下会把数据以序列化的形式缓存在JVM的堆内存中。但是并不是这两个方法被调用时立即缓存&#xff0c;而是触发后面的action时&#xff0c;该RDD将会被缓存在计算节点的内存中&#xff0c;并供…

杂记——14.git在idea上的使用及其实际开发介绍

这篇文章我们来讲一下git在idea上的使用&#xff0c;以及在实际开发过程中各个分支的使用及其具体的流程 目录 1.git在idea上的使用 1.1 idea上的git提交 1.2 idea上的分支切换 2.git在实际运用时的分支及其流程 2.1分支介绍 2.2具体流程 3.小结 1.git在idea上的使用 …

GraalVM-云原生时代的JVM(Java)

文章目录一、GraalVM是什么&#xff1f;二、GraalVM有哪些特点&#xff1f;2.1、高性能2.2、多语言支持2.3、互操作性2.4、安全性三、GraalVM的应用效果3.1、提高性能3.2、简化开发3.3、降低成本3.4、节省资源3.5、支持云环境四、使用GraalVM编译springboot应用程序4.1、下载并…