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

Java DES 加密解密完整指南:CBC 模式、PKCS5Padding、Base64 編碼與金鑰管理最佳實踐

     編輯:Java 程式設計入門

DES 概述與現狀

DES (Data Encryption Standard) 為 1977 年美國聯邦標準,56 位有效金鑰,64 位分組。現已不安全(1997 年暴力破解 < 24 小時),實務上已被 AES (128/192/256-bit) 取代。本文僅供維護舊系統、教學理解對稱加密原理參考,新專案嚴禁使用 DES。

核心參數說明

參數值說明
演算法/模式/填充DES/CBC/PKCS5PaddingCBC 模式需 IV,PKCS5Padding 自動填充至 8 位元組倍數
金鑰長度8 位元組 (56 位有效 + 8 位奇偶校驗)不足 8 位拋 InvalidKeyException
IV (初始向量)8 位元組CBC 模式必須,建議隨機生成並與密文一同傳輸
編碼Base64二進位密文安全傳輸(JSON、URL、XML)

完整工具類原始碼

import java.security.Key;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import org.apache.commons.codec.binary.Base64; // 需 commons-codec 依賴

public class Des {
    public static final String ALGORITHM = "DES/CBC/PKCS5Padding";
    // 固定 IV(示範用),生產環境必須隨機生成!
    private static final byte[] FIXED_IV = "********".getBytes(StandardCharsets.UTF_8);

    /** 加密:String → Base64 String */
    public static String encode(String key, String data) throws Exception {
        return encode(key, data.getBytes(StandardCharsets.UTF_8));
    }

    /** 加密:byte[] → Base64 String */
    public static String encode(String key, byte[] data) throws Exception {
        Key secretKey = generateKey(key);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(FIXED_IV));
        byte[] encrypted = cipher.doFinal(data);
        return Base64.encodeBase64String(encrypted);
    }

    /** 解密:Base64 String → byte[] */
    public static byte[] decode(String key, byte[] data) throws Exception {
        Key secretKey = generateKey(key);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(FIXED_IV));
        return cipher.doFinal(data);
    }

    /** 解密:Base64 String → String */
    public static String decodeValue(String key, String data) throws Exception {
        byte[] decoded = Base64.decodeBase64(data);
        byte[] decrypted = decode(key, decoded);
        String result = new String(decrypted, StandardCharsets.UTF_8);
        if (result.isEmpty()) throw new Exception("解密結果為空");
        return result;
    }

    private static Key generateKey(String key) throws Exception {
        if (key == null || key.getBytes(StandardCharsets.UTF_8).length < 8) {
            throw new IllegalArgumentException("金鑰長度不得小於 8 位元組");
        }
        DESKeySpec dks = new DESKeySpec(key.getBytes(StandardCharsets.UTF_8));
        SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
        return factory.generateSecret(dks);
    }
}

使用範例

public class DesTest {
    public static void main(String[] args) throws Exception {
        String key = "MySecretKey123"; // 至少 8 字元
        String original = "敏感資料:身分證 A123456789";

        // 加密
        String encrypted = Des.encode(key, original);
        System.out.println("密文: " + encrypted); // 如: xYz789...==

        // 解密
        String decrypted = Des.decodeValue(key, encrypted);
        System.out.println("明文: " + decrypted);

        // 驗證
        assert original.equals(decrypted);
    }
}

關鍵安全實踐(若必須用 DES)

  1. IV 必須隨機:每次加密生成新 SecureRandom 8 位元組 IV,密文格式:IV(8 bytes) + Ciphertext,解密時前 8 位切割作 IV。
  2. 金鑰管理:勿硬編碼,使用 KMS、環境變數、HashiCorp Vault、AWS KMS 等。
  3. 金鑰派生:若金鑰來自密碼,必須用 PBKDF2WithHmacSHA256 + 隨機 Salt + 10萬+ 迭代派生 8 位元組 DES 金鑰。
  4. 完整性驗證:DES 無內建認證,需額外計算 HMAC-SHA256(密文) 並驗證,防止填充神諭攻擊。
  5. 避免 ECB 模式:DES/ECB/PKCS5Padding 相同明文塊產生相同密文塊,嚴重洩露模式。

遷移至 AES(推薦)

// AES-256-CBC 範例
public class AesUtil {
    static final String ALGO = "AES/CBC/PKCS5Padding";
    static final int KEY_SIZE = 256;

    public static String encrypt(String key, String data) throws Exception {
        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
        // 若金鑰非 32 位元組,用 SHA-256 摘要截取
        Key secretKey = new SecretKeySpec(
            MessageDigest.getInstance("SHA-256").digest(keyBytes), "AES");

        Cipher cipher = Cipher.getInstance(ALGO);
        byte[] iv = new byte[16];
        new SecureRandom().nextBytes(iv);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv));

        byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        // 組合 IV + 密文
        byte[] combined = new byte[iv.length + encrypted.length];
        System.arraycopy(iv, 0, combined, 0, iv.length);
        System.arraycopy(encrypted, 0, combined, iv.length, encrypted.length);
        return Base64.encodeBase64String(combined);
    }
    // 解密對應拆分 IV...
}

常見異常與排查

異常原因解決
InvalidKeyException: Illegal key sizeJCE 限制金鑰長度(舊版 JDK)安裝 Unlimited Strength JCE Policy Files 或升級 JDK
BadPaddingException金鑰/IV 錯誤、資料損壞、填充模式不匹配核對金鑰、IV、填充模式、確認 Base64 正確解碼
InvalidAlgorithmParameterExceptionIV 長度不等於 8 (DES) 或 16 (AES)確保 IV 正確長度
NoSuchAlgorithmException提供者不支援 DES(極少見)確認 Security.getProviders() 包含 SunJCE

法律合規提醒

  • 中國《商用密碼管理條例》規定:涉及國家秘密、關鍵資訊基礎設施,必須使用國家認證密碼演算法 (SM2/SM3/SM4)。
  • 出口管制:舊版美國 EAR 限制強加密軟體出口,現已大幅放寬,但仍需留意目的地國家法規。
  • GDPR/個資法:加密是「適當技術措施」之一,但 DES 不再視為充分保護,監管機構可能判定不合規。

總結

  • DES 為歷史教學/舊系統維護用途,核心 API:Cipher.getInstance("DES/CBC/PKCS5Padding") + DESKeySpec + IvParameterSpec + Base64。
  • 新專案一律使用 AES-256-GCM 或 ChaCha20-Poly1305(AEAD 模式,同時提供機密性與完整性)。
  • 金鑰管理、IV 隨機化、完整性驗證、合規演算法選型,才是加密工程的核心難點。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved