当前位置:网站首页>用户密码加密编码使用 Bcrypt 代替 MD5,SHA1和SHA256
用户密码加密编码使用 Bcrypt 代替 MD5,SHA1和SHA256
2022-07-30 05:44:00 【victorkevin】
先入为主阐述一下Bcrypt编码算法两个优点
- 相同的原文每次编码出来的密文不相同
- 编码的速度很慢
是的这就是Bcrypt的优点,有经验的读者看上去会觉得奇怪,这还算得上是“优点”吗!特别是像编码的速度慢这一点。在这里为了说明这是所谓的“优点”不得不先从用户密码存储安全方面说起:
首先提及MD5编码算法大家马上就会联想到这是一种可以破解的加密算法,破解的方法主要是采用“彩虹表“(不清楚可在网上搜索),上述攻击方法最根本就是相同的原文经过MD5编码之后产生相同的密文,(简单说就是相同密码得出相同的密文,那么反过来就可以推导出原文),有经验的开发者会采用salt和多重MD5编码的方式来避免密文被破解,如果攻击者预先知道或者能够获取到足够多的信息上述两种方式也是很容易被攻破的,说到这里不喻而明Bcrypt第一个优点就是为了解决这种问题。当然MD5是一个相对过时的哈希编码算法,当前就算简单起见也应当选择SHA256等相对安全性更高的哈希编码算法。那第二点为何编码的速度很慢有什么帮助,你想想通过彩虹表攻击之前必需预先准备一套容量足够大的表碰撞表,如果能过MD5算法和Bcrypt作对比,因为Bcrypt足够慢而致依生成碰撞表付出更大量的计算量,这种困难可以使得生成碰撞表变得不现实,所以破解的难度就相应增大,正因为上述的原因所以说Bcrypt更适合作为用户密码加密编码的算法来使用,并且在使用的过程中不涉及多重编码,Salt和Pepper等问题,所以使用它的API使得代码更简洁和易懂。
以下是Bcrypt编码算法的实现,该类是引用自Spring Security模块中的
org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
/** * Implementation of PasswordEncoder that uses the BCrypt strong hashing function. Clients * can optionally supply a "strength" (a.k.a. log rounds in BCrypt) and a SecureRandom * instance. The larger the strength parameter the more work will have to be done * (exponentially) to hash the passwords. The default value is 10. * * @author Dave Syer * */
public class BCryptPasswordEncoder implements PasswordEncoder {
private Pattern BCRYPT_PATTERN = Pattern
.compile("\\A\\$2a?\\$\\d\\d\\$[./0-9A-Za-z]{53}");
private final Log logger = LogFactory.getLog(getClass());
private final int strength;
private final SecureRandom random;
public BCryptPasswordEncoder() {
this(-1);
}
/** * @param strength the log rounds to use, between 4 and 31 */
public BCryptPasswordEncoder(int strength) {
this(strength, null);
}
/** * @param strength the log rounds to use, between 4 and 31 * @param random the secure random instance to use * */
public BCryptPasswordEncoder(int strength, SecureRandom random) {
if (strength != -1 && (strength < BCrypt.MIN_LOG_ROUNDS || strength > BCrypt.MAX_LOG_ROUNDS)) {
throw new IllegalArgumentException("Bad strength");
}
this.strength = strength;
this.random = random;
}
public String encode(CharSequence rawPassword) {
String salt;
if (strength > 0) {
if (random != null) {
salt = BCrypt.gensalt(strength, random);
}
else {
salt = BCrypt.gensalt(strength);
}
}
else {
salt = BCrypt.gensalt();
}
return BCrypt.hashpw(rawPassword.toString(), salt);
}
public boolean matches(CharSequence rawPassword, String encodedPassword) {
if (encodedPassword == null || encodedPassword.length() == 0) {
logger.warn("Empty encoded password");
return false;
}
if (!BCRYPT_PATTERN.matcher(encodedPassword).matches()) {
logger.warn("Encoded password does not look like BCrypt");
return false;
}
return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
}
}
测试的代码如下:
@Test
public void testBCryptPasswordEncoder() {
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(6);
for (int i = 0; i < 3; i++) {
String encodedText = bCryptPasswordEncoder.encode("567123TR");
System.out.println(String.format("第%d次编码的结果:%s", i, encodedText));
}
}
最终测试的结果:
第0次编码的结果:$2a$06$ahAG0Hqch1kqCKueL8ecw.XFU8HHiO9k.HWuwXVd4iRiaVYd1Lko6
第1次编码的结果:$2a$06$IRmgGohEnNrC1xnhv0MomOly0AiIfBucBaTbx7QoZyj2lyilZCf9K
第2次编码的结果:$2a$06$dX.dZmRHMBC8RESaolKYU.u0cJmf70LRQbpnLvmZycOKPI4t34RJ2
扩展延伸
在某些应用场景BCrypt的就不大适用,如当系统需要采用Digest,HMac和AES对称加密等消息鉴别的场景,这类场景是需要共享一个相同的密钥的时候,Bcrypt因为相同原文输出不同的密钥,所以就无法共享相同的密钥。
Bcrypt编码算法应用在区块链技术上,很多人听说过比特币挖矿的原理是找sha256算法下计算出满足特定条件的nonce值,这种计算是要经过大量的运算,所以算力大的节点得到挖矿奖励的可能性越高,这点使得区块网络被算力大的控制,所以有些币考虑到这点,用Bcrypt算法替代sha256使得矿主无法通过投入算力来控制整个区块网络(因为Bcrypt算法慢),感兴趣的读者可以找相关资料。
最后基于上述建议在用户密码加密编码中放弃MD5吧,因为它即过时又缺乏安全性。
边栏推荐
- 【OS】操作系统高频面试题英文版(1)
- 生产力工具分享——简洁而不简单
- Function functional interface and application
- Invalid bound statement (not found)出现的原因和解决方法
- MySQL data types and footprint
- mysql is not an internal or external command, nor is it a runnable program or batch file to resolve
- MySQL achievement method 】 【 5 words, single table SQL queries
- MySQL - 多表查询与案例详解
- Bypassing the file upload vulnerability
- 函数的信息传递(C语言实践)
猜你喜欢

十四、Kotlin进阶学习:一、内联函数 inline;二、泛型;三、泛型约束;四、子类与子类型;

Flink-流/批/OLAP一体得到Flink引擎

Competition WP in May

protobuf coding and network communication applications (1)

Reasons and solutions for Invalid bound statement (not found)

常用损失函数(二):Dice Loss

为什么会出现梯度爆炸和梯度消失现象?怎么缓解这种现象的发生?

十五、Kotlin进阶学习:一、子类与子类型;二、协变;三、逆变;

TDengine集群搭建
![[MATLAB] Image Processing - Recognition of Traffic Signs](/img/45/1a5797a17ebf6db965a64c85e0f037.png)
[MATLAB] Image Processing - Recognition of Traffic Signs
随机推荐
Jdbc & Mysql timeout analysis
MySQL index optimization and failure scenarios
十八、Kotlin进阶学习:1、挂起函数执行的顺序;2、使用 async 和 await 异步执行挂起函数;3、协程的调度器;4、父子协程;
线程的5种状态
php vulnerability full solution
MySQL 索引的数据结构及类型
Flink CDC implements Postgres to MySQL streaming processing transmission case
抽象工厂模式(Swift 实现)
FastAPI Quick Start
二十一、Kotlin进阶学习:实现简单的网络访问封装
Obtain geographic location and coordinates according to ip address (offline method)
MySQL special statement and optimizer
The Request request body is repackaged to solve the problem that the request body can only be obtained once
oracle行转列、列转行总结
MySQL achievement method 】 【 5 words, single table SQL queries
sql concat() function
MySQL开窗函数
Mysql client common exception analysis
二叉树(一):深度优先遍历与广度优先遍历
Shardingsphere depots table and configuration example