目录
1. 背景介绍
2. MD5加密算法
2.1 MD5算法的介绍
2.2 MD5算法的缺点
3. 加盐算法
3.1 什么是加盐算法
3.2 加盐算法的演示
4. 总结
1. 背景介绍
加密密码是现代计算机系统中非常重要的一环,其 主要目的是保护用户的隐私和数据安全 。在不加密密码的情况下,
用户的账户和密码等信息会以明文的形式保存在计算机系统中 ,一旦这些信息被泄露,用户的隐私和数据就会面临很大的风险。
为了解决这个问题,计算机科学家们研究出了各种加密算法,将用户的密码等信息进行加密存储,提高用户的隐私和数据安全。其中,哈希算法是常用的一种加密算法,它将用户的密码等信息进行哈希运算,生成一串密文,然后将密文存储在数据库中。当用户登录时,系统会将用户输入的密码进行哈希运算,然后与数据库中的密文进行比对,如果一致,则表示用户身份验证通过,否则表示密码错误。
然而,即使使用哈希算法进行加密,也并不能完全保证密码的安全性。因为哈希算法存在一些安全漏洞,例如MD5算法就是一种典型的利用哈希算法进行加密的方法。
2. MD5加密算法
2.1 MD5算法的介绍
MD5(Message-Digest Algorithm 5)是一种常用的哈希算法,它将任意长度的消息压缩成一个128位的消息摘要,MD5的实现过程如下:
填充:将消息进行填充,使其长度是512位的倍数,填充的方式是在消息末尾加上一个1和若干个0,直到满足条件。
初始化:将4个32位寄存器A、B、C、D初始化为固定的常数。
处理消息:将每个512位的消息块进行处理,处理过程包括4个轮次,每个轮次处理16次,每次处理32位。
输出:将最后一个处理完的消息块的摘要输出,即为MD5摘要。
在Java中的Spring框架中,提供了将消息压缩成MD5消息摘要的方法,我们需要调用DigestUtils.md5DigestAsHex(byte[]
bytes)方法,在调用的过程中我们会发现,对于一个同样的数,所生成的MD5方法总是相同的,如下所示
public class Test {
public static void main(String[] args) {
String input1=DigestUtils.md5DigestAsHex("123456".getBytes());
String input2=DigestUtils.md5DigestAsHex("123456".getBytes());
System.out.println(input1);
System.out.println(input2);
}
}
2.2 MD5算法的缺点
对于123456而言,其经过MD5加密后输出的结果就是e10adc3949ba59abbe56e057f20f883e,这个值是固定的,即
每个消息都有其对应的MD5加密后的密码, 虽然说MD5算法是不可逆算法,即不可通过结果反推出原来,但是MD5算法存在的缺点在于其安全性太低。
对于想要破解MD5算法的人,他只需要准备一张 彩虹表, 彩虹表即一种密码破解技术,其基本思想是 预先计算出所有可能的输入和输出组合的哈希值
,然后存储在一个巨大的表格中,以便后续直接查找,因此MD5的安全性是比较低的,其关键在于随机性太低,于是密码加盐算法就诞生了。
3. 加盐算法
3.1 什么是加盐算法
密码加盐是一种增加密码安全性的技术,其主要思想是在密码加密的过程中,为密码添加一些额外的随机字符串或固定字符串,以增加密码的随机性和复杂性,从而提高密码的安全性。
密码加盐往往要生成一个随机数,然后将盐值和密码进行组合,再进行哈希运算。这样生成的密码哈希值就不仅取决于密码本身,还受到盐值的影响,攻击者无法通过简单的彩虹表等方式来破解密码。
例如:假设用户的密码是"password",盐值为"ilovecoding",则密码加盐的过程如下:
将盐值和密码组合,得到"ilovecodingpassword"。
对"ilovecodingpassword"进行哈希运算,得到密码的哈希值。
将密码哈希值存储在数据库中。
将密码加盐后,即使两个用户的密码相同,由于盐的不同,其哈希值也会不同,从而增加了破解难度,提高了密码的安全性。
3.2 加盐算法的演示
加盐算法的实现思路有许多种,我这里仅用一种来进行介绍演示。
使用加盐加密的过程其实不难理解, 关键点在于,当我们将加盐后的密码存储到数据库中后,我们如何验证用户输入密码的正确与否。
我们可以规定以下规范,加密过程如下:
1. 用户输入密码 password
2. 随机生成一个盐值 salt
3.将盐值salt与密码password进行拼接,然后将拼接后的值进行md5加密,得到一个加盐后的密码 saltpassword
- 将生成的盐值salt与加盐后的密码saltpassword进行拼合,中间以某个特定的符号进行分隔,并存储到数据库中
解密过程如下:
1.用户输入密码
2.我们根据用户id从数据库中调取存储的密码,并调用split方法,输入特定的分隔符
3.我们取分隔出的结果的第一个元素,即得到存储用户密码时的盐值
4.将得到的盐值与用户输入的密码进行与上面相同的加密过程,得到一个临时密码tmpPassword
5.将临时密码tmpPassword与存储到数据库的中的密码进行比对,正确时才登陆。
密码加盐的关键点还是在于,我们如何进行加密,同时
更核心的地方在于我们如何进行解密,以下为代码演示,UUID.randomUUID()方法可以生成随机字符, 要注意去掉随机字符的分隔符
//1. 加盐并生成密码
public static String encrypt(String password){
//盐值
String salt= UUID.randomUUID().toString().replace("-",""); //32位盐值
//生成加盐后密码
String saltPassword= DigestUtils.md5DigestAsHex((salt+password).getBytes());
//生成最终密码(保存到数据库中的密码,32位盐值+$+32位加盐之后的密码)
String finalPassword=salt+"$"+saltPassword;
return finalPassword;
}
我们可以重载encrypt方法,参数列表改为传入密码与盐值的重载方法
//2.生成加盐的密码(重载
public static String encrypt(String password,String salt){
//生成加盐密码
String saltPassword= DigestUtils.md5DigestAsHex((salt+password).getBytes());
//生成最终密码
String finalPassword=salt+"$"+saltPassword;
return finalPassword;
}
解密过程代码如下:
//3.验证密码
//inputPassword为用户输入明文密码
//finalPassword为数据库保存的密码
public static boolean check(String inputPassword,String finalPassword){
if(StringUtils.hasLength(inputPassword) && StringUtils.hasLength(finalPassword) && finalPassword.length()==65){
//得到盐值
String salt=finalPassword.split("\\$")[0];
// 进行加密得到相应的密码
String confirmPassword=encrypt(inputPassword,salt);
//对比两个密码是否相同
return confirmPassword.equals(finalPassword);
}
return false;
}
4. 总结
虽然密码加盐可以有效提高密码的安全性,但也存在一些缺点和限制。
密码加盐的缺点如下:
需要额外的存储空间:密码加盐需要将盐值和哈希值一起存储在数据库中,这就需要更多的存储空间。
盐值的生成需要保证足够随机:盐值的生成需要保证足够随机和复杂,否则攻击者可能会推算出盐值,从而破解密码。
盐值的传输需要保证安全:盐值的传输也需要保证安全,否则攻击者可以通过截取盐值来破解密码。
盐值的使用需要考虑兼容性:如果不同的系统使用了不同的盐值生成方法,可能会导致兼容性问题。
可能仍然存在彩虹表攻击:虽然加盐可以防止彩虹表攻击,但仍然有可能被攻击者通过暴力破解法攻破密码。
总而言之,密码加盐是一种简单而有效的密码安全技术,通过增加密码的随机性和复杂性,可以有效防止密码破解攻击,提高密码的安全性。在实际应用中,我们应该采用密码加盐的方式来保护用户的密码,并且选择足够随机和复杂的盐值,以确保密码加盐的效果。
学习计划安排
我一共划分了六个阶段,但并不是说你得学完全部才能上手工作,对于一些初级岗位,学到第三四个阶段就足矣~
这里我整合并且整理成了一份【282G】的网络安全从零基础入门到进阶资料包,需要的小伙伴可以扫描下方CSDN官方合作二维码免费领取哦,无偿分享!!!
如果你对网络安全入门感兴趣,那么你需要的话可以
点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!
①网络安全学习路线
②上百份渗透测试电子书
③安全攻防357页笔记
④50份安全攻防面试指南
⑤安全红队渗透工具包
⑥HW护网行动经验总结
⑦100个漏洞实战案例
⑧安全大厂内部视频资源
⑨历年CTF夺旗赛题解析