package com.cdzy.common.utils; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.SecureRandom; import java.util.Base64; import java.util.HexFormat; /** * SHA-256 加盐加密工具类 */ public class SHA256WithSaltUtil { private static final int SALT_LENGTH = 16; // 盐值长度(16字节 = 128位) private static final String ALGORITHM = "SHA-256"; private static final HexFormat HEX_FORMAT = HexFormat.of(); /** * 生成随机盐值 */ public static String generateSalt() { SecureRandom random = new SecureRandom(); byte[] salt = new byte[SALT_LENGTH]; random.nextBytes(salt); return Base64.getEncoder().encodeToString(salt); } /** * 加密密码(SHA-256 + 盐值) * @param password 原始密码 * @param salt 盐值(如果为null则自动生成) * @return 返回加密后的密码和盐值组合字符串(格式:密文:盐值) */ public static String encrypt(String password, String salt) { try { // 如果未提供盐值,则生成新盐值 String usedSalt = (salt == null) ? generateSalt() : salt; MessageDigest md = MessageDigest.getInstance(ALGORITHM); md.update(Base64.getDecoder().decode(usedSalt)); // 加入盐值 byte[] hash = md.digest(password.getBytes(StandardCharsets.UTF_8)); // 返回格式:HEX(哈希值):Base64(盐值) return HEX_FORMAT.formatHex(hash) + ":" + usedSalt; } catch (Exception e) { throw new RuntimeException("密码加密失败", e); } } /** * 验证密码 * @param inputPassword 用户输入的密码 * @param storedHash 数据库存储的加密字符串(格式:密文:盐值) * @return 是否匹配 */ public static boolean verify(String inputPassword, String storedHash) { if (inputPassword == null || storedHash == null) { return false; } String[] parts = storedHash.split(":"); if (parts.length != 2) { throw new IllegalArgumentException("存储的密码格式无效"); } String inputHash = encrypt(inputPassword, parts[1]); return inputHash.equals(storedHash); } // 测试示例 public static void main(String[] args) { String password = "admin123"; // 加密 String encrypted = encrypt(password, null); System.out.println("加密结果: " + encrypted); // 验证 boolean matched = verify(password, encrypted); System.out.println("验证结果: " + matched); // 错误密码测试 boolean wrongMatch = verify("wrongPassword", encrypted); System.out.println("错误密码测试: " + wrongMatch); } }