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 加盐算法的演示
加盐算法的实现思路有许多种,我这里仅用一种来进行介绍演示。
使用加盐加密的过程其实不难理解,关键点在于,当我们将加盐后的密码存储到数据库中后,我们如何验证用户输入密码的正确与否。
我们可以规定以下规范,加密过程如下:
用户输入密码 password
随机生成一个盐值 salt
3.将盐值salt与密码password进行拼接,然后将拼接后的值进行md5加密,得到一个加盐后的密码 saltpassword
4.将生成的盐值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. 总结
虽然密码加盐可以有效提高密码的安全性,但也存在一些缺点和限制。
密码加盐的缺点如下:
- 需要额外的存储空间:密码加盐需要将盐值和哈希值一起存储在数据库中,这就需要更多的存储空间。
- 盐值的生成需要保证足够随机:盐值的生成需要保证足够随机和复杂,否则攻击者可能会推算出盐值,从而破解密码。
- 盐值的传输需要保证安全:盐值的传输也需要保证安全,否则攻击者可以通过截取盐值来破解密码。
- 盐值的使用需要考虑兼容性:如果不同的系统使用了不同的盐值生成方法,可能会导致兼容性问题。
- 可能仍然存在彩虹表攻击:虽然加盐可以防止彩虹表攻击,但仍然有可能被攻击者通过暴力破解法攻破密码。
总而言之,密码加盐是一种简单而有效的密码安全技术,通过增加密码的随机性和复杂性,可以有效防止密码破解攻击,提高密码的安全性。在实际应用中,我们应该采用密码加盐的方式来保护用户的密码,并且选择足够随机和复杂的盐值,以确保密码加盐的效果。
版权归原作者 yss233333 所有, 如有侵权,请联系我们删除。