java它以平台無關性
安全性
面向對象
分布式
鍵壯性等特點贏得了眾多程序員的青睐
但人們在使用java的過程中
會發現它有幾個致命的弱點
運行速度慢
用戶使用不便
源代碼保護機制不夠安全
特別是在保護源代碼方面
java是基於解釋一種叫java字節碼的中間代碼來運行其程序的
而且jvm比計算機的微處理器要簡單的多
文檔也很齊全
結果造成其目標程序很容易被反編譯
而且所得代碼和其原始代碼十分相似
甚至可以一模一樣
可讀性相當好
這就給java的代碼保護帶來了不利
但要實現java程序的保護
也不是不可能的
經研究和總結
至少有三種實現方式
混淆器
網絡加載重要類
加密重要類
一
混淆器
目前
開發人員使用的比較多的保護代碼的方法是用混淆器
混淆器是采用一些方法將類
變量
方法
包的名字改為無意義的字符串
使用非法的字符代替符號
貼加一些代碼使反編譯軟件崩潰
貼加一些無關的指令或永遠執行不到的指令等使反編譯無法成功或所得的代碼可讀性很差
這樣就實現了反反編譯的目的
但是
如果在編寫軟件時
在軟件中寫入某些注冊信息
或一些簡單的算法
通過反編譯
還是有可能得到這些信息的
從而未能達到保護軟件的目的
反編譯器與混淆器之間的斗爭是永無止盡的
所以從其他角度去保護java的源代碼是很有必要
二
網絡加載重要類
在java中提供了一個ClassLoader類
這個類可以讓我們使用類加載器將所需要的java字節碼文件加載到jvm中
我們通過重寫這個類
可以實現從網絡通過url加載java字節碼文件
這樣
我們就可以把一些重要的
隱秘的class放在網絡服務器上
通過口令去檢驗是否有權限下載該類
從而實現java代碼保護的目的
其次在java中正好提供了URLClassLoader這個類
通過此類
正好可以實現我們的目的
URLClassLoader類的基本使用方法是通過一個URL類型的數組告訴URLClassLoader類的對象是從什麼地方加載類
然後使用loadclass()方法
從給定的URL中加載字節碼文件
獲得它的方法
然後再執行
具體步驟如下
創建URL
URL url[]={
new URL(
file:///c:/classloader/web
)
new URL(
/javaclass/
) };
創建URLClassLoader對象
URLClassLoader cl=new URLClassLoader(url)
使用URLClassLoader對象加載字節碼文件
Class class=cl
loadClass(
class
)
執行靜態方法
Class getarg[]={
(new String [
])
getClass() };
Method m=class
getMethod(
main
getarg)
String[] myl={
arg
passed
arg
passed
)
Object myarg[]={myl};
m
invole(null
myarg)
三
加密重要類
使用網絡加載重要類的方法固然有一定的用處
但是
在遇到無網絡的情況時
還是無法解決我們的問題
對於這種情況
我們只能把所有文件放在本地計算機上
那麼
對此我們該怎麼做才能保護好java代碼呢?其實
要實現這一點
並不難
只需要對一些重要的類實行加密就可以了
當然
在裝載時
加密的類是需要解密才能被ClassLoader識別的
所以
我們必須自己創建ClassLoader類
在標准java api中ClassLoader有幾個重要的方法
創建定制ClassLoader時
我們只需覆蓋其中的一個
即loadClass
添加獲取原始類文件數據的代碼
這個方法有兩個參數
類的名字
以及一個表示JVM是否要求解析類名字的標記(即是否同時裝入有依賴關系的類)
如果這個標記為true
我們只需在返回JVM之前調用resolveClass
原代碼如下
public Class loadClass( String name
boolean resolve )
throws ClassNotFoundException {
try { Class clasz = null;
//步驟
:如果類已經在系統緩沖之中
我們就不需要再次裝入它
clasz = findLoadedClass( name )
if (clasz != null)
return clasz;
byte classData[] = /* 通過某種方法獲取字節碼數據*/;
if (classData != null) {
clasz = defineClass( name
classData
classData
length )
}
//步驟
:如果上面沒有成功
if (clasz == null)
clasz = findSystemClass( name )
//步驟
:如有必要
則裝入相關的類
if (resolve && clasz != null)
resolveClass( clasz )
return clasz;
} catch( IOException ie ) {
throw new ClassNotFoundException( ie
toString() )
} catch( GeneralSecurityException gse ) {
throw new ClassNotFoundException( gse
toString() )
} }
代碼中的大部分對所有ClassLoader對象來說都一樣
但有一小部分是特有的
在處理過程中
ClassLoader對象要用到其他幾個輔助方法
findLoadedClass:用來進行檢查
以便確認被請求的類當前是否存在
loadClass方法應該首先調用它
defineClass:獲得原始類文件字節碼數據之後
調用defineClass把它轉換成對象
任何loadClass實現都必須調用這個方法
findSystemClass:提供默認ClassLoader的支持
如果用來尋找類的定制方法不能找到指定的類
則可以調用該方法嘗試默認的裝入方式
resolveClass:當JVM想要裝入的不僅包括指定的類
而且還包括該類引用的所有其他類時
它會把loadClass的resolve參數設置成true
這時
我們必須在返回剛剛裝入的Class對象給調用者之前調用resolveClass
接下來就是加密解密部分
Java加密擴展即Java Cryptography Extension
簡稱JCE
是Sun的加密服務軟件
包含了加密和密匙生成功能
我們可以用DES算法加密和解密字節碼
用JCE加密和解密數據是要遵循一些基本步驟的
加密完成後
就是通過解密來獲取原始類的java字節碼
可以通過一個DecryptStart程序運行經過加密的應用
應用本身經過了加密
但啟動程序DecryptStart沒有加密
攻擊者可以反編譯啟動程序並修改它
把解密後的類文件保存到磁盤
降低這種風險的辦法之一是對啟動程序進行高質量的模糊處理
或者
啟動程序也可以采用直接編譯成機器語言的代碼
使得啟動程序具有傳統執行文件格式的安全性
比如使用java的jini技術
來實現解密部分
就可以作到
當然
這是需要付出一定的代價的
就是喪失了java的最大特點
平台無關性
不過
jni技術可以用c語言在多種平台實現
我們可以在不同的平台編寫不同的啟動程序
四
綜合實例
對於一些需要網絡支持的軟件來說
可以建立一個Web站點
在站點上存放該軟件的關鍵類
並且建立用戶管理機制
用戶直接登陸網站進行確認
是許可用戶
則發放解密key文件
讓其下載關鍵類
在本地解密運行
這樣作的優點是建立的Web站點可以有效的管理密鑰以及用戶資料
從而起到加強保護軟件源代碼的作用
並方便軟件升級
用C/S結構是不錯的選擇
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26554.html