java密码加盐操作

1.MD5码的概述

MD5(Message Digest Algorithm 5)是一种广泛使用的哈希函数算法,用于将任意长度的数据转换成固定长度的散列值。它由Ronald Rivest于1991年设计,并被广泛应用于密码学和数据完整性校验等领域。MD5算法的输入可以是任意长度的数据,输出是一个128位(16字节)的散列值。该散列值通常表示为一个32位十六进制数字,例如:5d41402abc4b2a76b9719d911017c592。
MD5算法的核心原理是将输入数据分成一系列固定大小的数据块,并对每个数据块进行一系列复杂的运算操作,最终得到一个散列值。这个散列值具有以下特点:

固定长度:无论输入数据的大小,MD5算法的输出始终是128位(16字节)长。
唯一性:对于不同的输入数据,其散列值应当是唯一的,即不同的输入应当生成不同的散列值。
不可逆性:无法通过散列值逆推出原始输入数据。也就是说,即使散列值相同,无法确定其对应的具体输入数据。
高效性:MD5算法的计算速度相对较快,适用于快速生成散列值。

由于其设计上的弱点,MD5算法容易受到碰撞攻击(collision attack)或可使用彩虹表进行破解。碰撞攻击是指找到两个不同的输入数据,但它们却产生相同的MD5散列值的情况。
彩虹表(Rainbow Table)是一种用于加速密码破解的预计算技术。通过预先计算一系列可能的输入和其对应的散列值,然后通过比对查找输入值。

2.传统用户注册登录

通过用户在前端输入用户名和密码,后端得到用户名和密码后将其密码进行MD5编码后,存入sql表中;
待用户下次登陆时,同样输入用户名和密码,发送给后端,用户名找到sql中编码后的密码,因为MD5码具有不可逆性,故而需将输入的密码进行在次MD5加密,然后与sql中的密码进行比对,相同则返回登录成功。

3.密码加盐

密码加盐是一种增加密码安全性的技术。在密码加盐过程中,一个随机的字符串(称为盐)会与密码进行组合,然后对组合后的字符串进行哈希运算,最终存储在系统中。
盐的作用是为了使相同密码在哈希后产生不同的结果。这是因为即使两个用户使用了相同的密码,但由于他们的盐不同,最终生成的哈希值也会不同。这种方法的目的是增加密码破解的难度,即使攻击者获得了哈希值,他们也无法轻易地通过查找常见的明文密码来猜测原始密码。
密码加盐还能够防止使用彩虹表(rainbow table)进行暴力破解。彩虹表是一种预先计算并存储了密码哈希值和对应明文密码的表格,可以用于快速查找哈希值对应的明文密码。然而,由于每个用户都有唯一的盐值,攻击者无法事先生成包含所有可能盐值的彩虹表,从而增加了破解的难度。
总结来说,密码加盐是一种增加密码安全性的方法,通过随机盐值的引入,使相同密码在哈希后产生不同的结果,增加了密码破解的难度,并有效防止了彩虹表攻击。

4.代码举例

package com.example.demo.common;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import java.util.UUID;

/**
 * 密码工具类
 * 加盐加密 / 加盐解密
 */
public class PasswordTools {

    /**
     * 加盐加密
     *
     * @param password 明文密码
     * @return 加盐加密的密码
     */
    public static String encrypt(String password) {
        // 1.产生盐值
        String salt = UUID.randomUUID().toString().replace("-", "");
        // 2.使用(盐值+明文密码)得到加密的密码
        String finalPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
        // 3.将盐值和加密的密码共同返回(合并盐值和加密密码)
        String dbPassword = salt + "$" + finalPassword;
        return dbPassword;
    }

    /**
     * 加盐加密
     *
     * @param password 明文密码
     * @param salt     盐值
     * @return 加盐加密的密码
     */
    public static String encrypt(String password, String salt) {
        // 1.使用(盐值+明文密码)得到加密的密码
        String finalPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
        // 2.将盐值和加密的密码共同返回(合并盐值和加密密码)
        String dbPassword = salt + "$" + finalPassword;
        return dbPassword;
    }

    /**
     * 验证加盐加密密码
     *
     * @param password   明文密码(不一定对,需要验证明文密码)
     * @param dbPassword 数据库存储的密码(包含:salt+$+加盐加密密码)
     * @return true=密码正确
     */
    public static boolean decrypt(String password, String dbPassword) {
        boolean result = false;
        if (StringUtils.hasLength(password) && StringUtils.hasLength(dbPassword) &&
                dbPassword.length() == 65 && dbPassword.contains("$")) { // 参数正确
            // 1.得到盐值
            String[] passwrodArr = dbPassword.split("\\$");
            // 1.1 盐值
            String salt = passwrodArr[0];
            // 2.生成验证密码的加盐加密密码
            String checkPassword = encrypt(password, salt);
            if (dbPassword.equals(checkPassword)) {
                result = true;
            }
        }
        return result;
    }
}

你可能感兴趣的:(java,开发语言)