首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 加密算法實戰:MD5、雙重 MD5、HMAC-SHA1、XOR 混淆完整工具類

     編輯:Java 綜合教學

Java 加密工具類全解析:MD5、HMAC-SHA1、XOR 混淆、Base64 編碼的生產級實現

本文提供一個生產就緒的 EncryptUtil,涵蓋單向雜湊 (MD5)、鍵控雜湊 (HMAC-SHA1)、可逆混淆 (XOR)、十六進制/Base64 編碼轉換,並解析每種算法的適用場景、安全性與效能特徵。

完整工具類代碼

package com.ompa.common.utils;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class EncryptUtil {
    
    // ===== 常量配置 =====
    private static final String MD5_ALGORITHM = "MD5";
    private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
    private static final String CHARSET = StandardCharsets.UTF_8.name();
    
    // 生產環境應從配置中心/環境變量讀取,不可硬編碼!
    private static final String HMAC_KEY = System.getenv().getOrDefault("HMAC_SHA1_KEY", "default_secret_key_change_me");
    private static final String XOR_KEY = System.getenv().getOrDefault("XOR_OBFUSCATE_KEY", "t");
    
    // ===== 十六進制編碼/解碼 =====
    
    /**
     * 字節數組轉小寫十六進制字串 (高效查表法)
     */
    public static String bytesToHex(byte[] bytes) {
        if (bytes == null) return "";
        char[] hexChars = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
        char[] result = new char[bytes.length * 2];
        for (int i = 0, j = 0; i < bytes.length; i++) {
            int v = bytes[i] & 0xFF;
            result[j++] = hexChars[v >>> 4];
            result[j++] = hexChars[v & 0x0F];
        }
        return new String(result);
    }
    
    /**
     * 十六進制字串轉字節數組
     */
    public static byte[] hexToBytes(String hex) {
        if (hex == null || hex.length() % 2 != 0) return new byte[0];
        byte[] bytes = new byte[hex.length() / 2];
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) Integer.parseInt(hex.substring(i*2, i*2+2), 16);
        }
        return bytes;
    }
    
    // ===== MD5 系列 =====
    
    /**
     * 標準 MD5 雜湊 (32 位十六進制)
     * @param input 輸入字串
     * @return 32 位小寫十六進制 MD5
     */
    public static String md5(String input) {
        return md5(input.getBytes(StandardCharsets.UTF_8));
    }
    
    public static String md5(byte[] input) {
        try {
            MessageDigest md = MessageDigest.getInstance(MD5_ALGORITHM);
            byte[] digest = md.digest(input);
            return bytesToHex(digest);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5 algorithm not available", e);
        }
    }
    
    /**
     * 雙重 MD5 (md5(md5(input))) - 早期防彩虹表常用,現不建議作為密碼存儲
     */
    public static String doubleMd5(String input) {
        return md5(md5(input));
    }
    
    // ===== HMAC-SHA1 (鍵控雜湊) =====
    
    /**
     * HMAC-SHA1 簽名
     * @param data 待簽名數據
     * @param key  密鑰
     * @return 十六進制簽名
     */
    public static String hmacSha1(String data, String key) {
        try {
            SecretKey secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), HMAC_SHA1_ALGORITHM);
            Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
            mac.init(secretKey);
            byte[] result = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
            return bytesToHex(result);
        } catch (Exception e) {
            throw new RuntimeException("HMAC-SHA1 calculation failed", e);
        }
    }
    
    /**
     * 使用預設密鑰的 HMAC-SHA1
     */
    public static String hmacSha1(String data) {
        return hmacSha1(data, HMAC_KEY);
    }
    
    // ===== XOR 可逆混淆 (非加密,僅輕度混淆) =====
    
    /**
     * XOR 字符級混淆/還原 (對稱操作)
     * @param input 輸入字串
     * @param keyChar 单字符密鑰
     * @return 混淆後字串 (再次調用可還原)
     */
    public static String xorObfuscate(String input, char keyChar) {
        if (input == null) return null;
        char[] chars = input.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            chars[i] ^= keyChar;
        }
        return new String(chars);
    }
    
    public static String xorObfuscate(String input) {
        return xorObfuscate(input, XOR_KEY.charAt(0));
    }
    
    // ===== Base64 編碼 =====
    
    public static String base64Encode(byte[] input) {
        return Base64.getEncoder().encodeToString(input);
    }
    
    public static String base64Encode(String input) {
        return base64Encode(input.getBytes(StandardCharsets.UTF_8));
    }
    
    public static byte[] base64Decode(String input) {
        return Base64.getDecoder().decode(input);
    }
    
    public static String base64DecodeToString(String input) {
        return new String(base64Decode(input), StandardCharsets.UTF_8);
    }
    
    // ===== 測試主方法 =====
    public static void main(String[] args) {
        String test = "123456";
        
        System.out.println("原文: " + test);
        System.out.println("MD5: " + md5(test));
        System.out.println("Double MD5: " + doubleMd5(test));
        System.out.println("HMAC-SHA1: " + hmacSha1(test));
        System.out.println("XOR 混淆: " + xorObfuscate(test));
        System.out.println("XOR 還原: " + xorObfuscate(xorObfuscate(test)));
        System.out.println("Base64: " + base64Encode(test));
    }
}

算法選型指南

算法類型可逆性安全強度適用場景不適用場景
MD5單向雜湊不可逆低 (碰撞攻擊可行)文件完整性校驗、非敏感 ID 生成、緩存 Key密碼存儲、簽名驗證、安全關鍵場景
Double MD5單向雜湊不可逆低 (本質仍是 MD5)舊系統兼容、簡單防彩虹表任何新系統密碼存儲
HMAC-SHA1鍵控雜湊不可逆中 (SHA-1 理論弱點,HMAC 結構尚可)API 簽名驗證、Token 生成、消息完整性高安全簽名 (建議 HMAC-SHA256)
XOR 混淆可逆混淆可逆極低 (已知明文攻擊秒破)配置文件輕度混淆、傳輸簡要反爬蟲、測試數據遮罩任何機密數據保護、密碼存儲、Token 生成
SHA-256單向雜湊不可逆高 (當前推薦標準)密碼雜湊 (配合鹽值)、區塊鏈、數字簽名需可逆場景
BCrypt/SCrypt/Argon2密碼雜湊不可逆極高 (可調計算成本)用戶密碼存儲首選高頻驗證場景 (計算慢)
AES-GCM對稱加密可逆高 (認證加密)敏感數據存儲、Token 加密、配置文件加密需非對稱場景

密碼存儲最佳實踐 (2024 標準)

// 使用 Spring Security BCrypt (內建鹽值、可調成本)
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Component
public class PasswordService {
    // strength 10-12 適中,12 以上較慢但更安全
    private final PasswordEncoder encoder = new BCryptPasswordEncoder(12);
    
    public String encode(String rawPassword) {
        return encoder.encode(rawPassword); // 自動生成鹽值、雜湊
    }
    
    public boolean matches(String rawPassword, String encodedPassword) {
        return encoder.matches(rawPassword, encodedPassword);
    }
}

API 簽名驗證模式 (HMAC-SHA256 推薦)

public class ApiSignUtil {
    
    // 客戶端簽名生成
    public static String generateSign(Map params, String secretKey) {
        // 1. 參數按 Key 字典序排序
        String signContent = params.entrySet().stream()
            .filter(e -> e.getValue() != null && !"sign".equals(e.getKey()))
            .sorted(Map.Entry.comparingByKey())
            .map(e -> e.getKey() + "=" + e.getValue())
            .collect(Collectors.joining("&"));
        
        // 2. HMAC-SHA256 簽名
        return hmacSha256(signContent, secretKey);
    }
    
    // 服務端驗證
    public static boolean verifySign(Map params, String secretKey) {
        String clientSign = params.get("sign");
        if (clientSign == null) return false;
        
        String serverSign = generateSign(params, secretKey);
        // 使用恆定時間比較防止時序攻擊
        return MessageDigest.isEqual(clientSign.getBytes(), serverSign.getBytes());
    }
    
    private static String hmacSha256(String data, String key) {
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
            return bytesToHex(mac.doFinal(data.getBytes(StandardCharsets.UTF_8)));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

常見誤區與修正

  1. 誤區:MD5 加密密碼 → 修正:使用 BCrypt/Argon2,MD5 只適合完整性校驗
  2. 誤區:Double MD5 增加安全性 → 修正:本質未變,彩虹表可預計算雙重 MD5
  3. 誤區:XOR 可作為加密 → 修正:僅混淆,已知一組明密文即可破解密鑰
  4. 誤區:Base64 是加密 → 修正:僅編碼,無任何保密性
  5. 誤區:硬編碼密鑰 → 修正:密鑰必須從配置中心、環境變量、密碼管理系統獲取
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved