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

Java 類加密保護源代碼:自定義 ClassLoader 實現即時解密方案

     編輯:Java 相關知識

為什麼需要加密

Java 字節碼易被反編譯(JD-GUI、Fernflower 等工具),源代碼幾乎裸奔。傳統混淆(ProGuard 等)僅增加逆向難度,無法根治。加密 + 自定義 ClassLoader 實現「運行時解密、內存中執行、磁盤無明文」,大幅提高逆向成本。

核心原理:ClassLoader 機制

JVM 載入類時委託 ClassLoader 尋找字節碼、轉為 Class 對象。繼承 ClassLoader 並重寫 loadClass(),即可在定義類前插入解密邏輯。解密後的字節碼僅存在於 JVM 內存,不落盤。

關鍵方法解析

方法作用
findLoadedClass檢查類是否已載入,避免重複載入
defineClass將字節碼數組轉為 Class 對象(核心)
findSystemClass委託系統類加載器載入(如 JDK 核心類)
resolveClass解析類的符號引用(當 resolve=true 時調用)

JCE 加密/解密流程(以 DES 為例)

1. 生成密鑰

SecureRandom sr = new SecureRandom();
KeyGenerator kg = KeyGenerator.getInstance("DES");
kg.init(sr);
SecretKey key = kg.generateKey();
byte[] rawKeyData = key.getEncoded(); // 保存供後續使用

2. 加密類文件(發布前執行)

DESKeySpec dks = new DESKeySpec(rawKeyData);
SecretKeyFactory kf = SecretKeyFactory.getInstance("DES");
SecretKey key = kf.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key, sr);
byte[] encrypted = cipher.doFinal(classBytes); // 寫入 .class 文件

3. ClassLoader 中解密(運行時)

cipher.init(Cipher.DECRYPT_MODE, key, sr);
byte[] decrypted = cipher.doFinal(encryptedClassBytes);
Class clazz = defineClass(name, decrypted, 0, decrypted.length);

完整應用示例結構

  • GenerateKey:生成密鑰文件 key.data
  • EncryptClasses:加密 App.class、Foo.class、Bar.class
  • DecryptStart:自定義 ClassLoader + 主程序入口,讀取密鑰、載入並運行加密應用

運行方式:java DecryptStart key.data App arg0 arg1

安全性邊界與對策

  • 啟動類未加密:攻擊者可修改 DecryptStart 落盤解密後字節碼 → 對啟動類做深度混淆或編譯為本地機器碼
  • JVM 自身不安全:惡意 JVM 可從 ClassLoader 外獲取解密字節碼 → 無完美方案,屬於信任基礎設施範疇
  • 密鑰洩露 = 失效:密鑰保護是核心,建議硬件加密模塊(HSM)或白盒加密

結語

「無完全安全的系統」,但加密 ClassLoader 方案在不修改業務代碼前提下,將逆向門檻從「反編譯工具一鍵搞定」提升至「需分析 JVM 內存/調試 ClassLoader」,足以保護大多數商業邏輯與知識產權。

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