首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Java DES 加密解密:IllegalBlockSizeException 異常完整解決方案

     編輯:程式設計疑難解答

異常現象

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher

解密時拋出塊大小非法異常,且後續出現 NullPointerException。

根本原因分析

  1. 缺少填充模式指定:原代碼 Cipher.getInstance("DES") 使用預設模式 ECB/NoPadding,要求輸入長度為 8 字節倍數。實際數據長度不固定,解密失敗。
  2. 未指定初始化向量 (IV):CBC 模式需 IV,原代碼未提供,導致加密解密不一致。
  3. 密鑰管理缺陷:靜態初始化 KeyGenerator 每次生成隨機密鑰,導致加密解密密鑰不一致。
  4. 異常吞沒:catch 僅打印堆疊,返回 null 或空字串,後續操作觸發 NPE。

正確實現:DES/CBC/PKCS5Padding 完整類

public class DESUtil {
    private static final String ALGORITHM = "DES/CBC/PKCS5Padding";
    private static final String KEY = "19491001"; // 8 字節密鑰,生產環境應從配置讀取

    private static SecretKeySpec getKeySpec() {
        return new SecretKeySpec(KEY.getBytes(StandardCharsets.UTF_8), "DES");
    }

    private static IvParameterSpec getIvSpec() {
        return new IvParameterSpec(KEY.getBytes(StandardCharsets.UTF_8)); // 簡化:密鑰作 IV,實際應隨機生成並隨密文存儲
    }

    // 加密:返回 Base64 字串,便於傳輸
    public static String encrypt(String plainText) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, getKeySpec(), getIvSpec());
        byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    // 解密:輸入 Base64 字串
    public static String decrypt(String encryptedBase64) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, getKeySpec(), getIvSpec());
        byte[] decoded = Base64.getDecoder().decode(encryptedBase64);
        byte[] decrypted = cipher.doFinal(decoded);
        return new String(decrypted, StandardCharsets.UTF_8);
    }

    // 測試
    public static void main(String[] args) throws Exception {
        String original = "product_id=12345";
        String encrypted = encrypt(original);
        String decrypted = decrypt(encrypted);
        System.out.println("加密: " + encrypted);
        System.out.println("解密: " + decrypted);
    }
}

關鍵修正點

  • 明確指定 DES/CBC/PKCS5Padding,自動處理填充,無需手動補齊 8 字節。
  • 使用固定密鑰(或雙方協商密鑰),確保加解密一致。
  • 密文以 Base64 編碼傳輸,避免二進制數據在 URL/表單中損壞。
  • 異常向上拋出,由調用者統一處理,避免空指針。

JSP/Action 整合示例

// JSP 加密傳參
String encId = DESUtil.encrypt(request.getParameter("product_id"));
response.sendRedirect("action.do?encId=" + URLEncoder.encode(encId, "UTF-8"));

// Action 解密
String encId = request.getParameter("encId");
String productId = DESUtil.decrypt(encId);

安全建議

DES 已不安全(密鑰僅 56 位),生產環境強烈建議升級至 AES-256-GCM,並使用隨機 IV、認證加密防篡改。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved