如何有效防止Java程序源碼被人偷窺?(3)_Mssql數(shù)據(jù)庫教程
推薦:如何快速生成100萬不重復的8位編號最近在論壇看到有人問,如何快速生成100萬不重復的8位編號,對于這個問題,有幾點是需要注意的: 1. 如何生成8位隨機數(shù),生成的數(shù)越隨機,重復的可能性當然越小 2. 控制不重復
四、應用實例
前面介紹了如何加密和解密數(shù)據(jù)。要部署一個經(jīng)過加密的應用,步驟如下:
步驟1:創(chuàng)建應用。我們的例子包含一個App主類,兩個輔助類(分別稱為Foo和Bar)。這個應用沒有什么實際功用,但只要我們能夠加密這個應用,加密其他應用也就不在話下。
步驟2:生成一個安全密匙。在命令行,利用GenerateKey工具(參見GenerateKey.java)把密匙寫入一個文件: % java GenerateKey key.data
步驟3:加密應用。在命令行,利用EncryptClasses工具(參見EncryptClasses.java)加密應用的類: % java EncryptClasses key.data App.class Foo.class Bar.class
該命令把每一個.class文件替換成它們各自的加密版本。
步驟4:運行經(jīng)過加密的應用。用戶通過一個DecryptStart程序運行經(jīng)過加密的應用。DecryptStart程序如Listing 6所示。 【Listing 6:DecryptStart.java,啟動被加密應用的程序】
| 以下為引用的內(nèi)容: import java.io.*; import java.security.*; import java.lang.reflect.*; import javax.crypto.*; import javax.crypto.spec.*; public class DecryptStart extends ClassLoader { // 這些對象在構(gòu)造函數(shù)中設置, // 以后loadClass()方法將利用它們解密類 private SecretKey key; private Cipher cipher; // 構(gòu)造函數(shù):設置解密所需要的對象 public DecryptStart( SecretKey key ) throws GeneralSecurityException, IOException { this.key = key; String algorithm = "DES"; SecureRandom sr = new SecureRandom(); System.err.println( "[DecryptStart: creating cipher]" ); cipher = Cipher.getInstance( algorithm ); cipher.init( Cipher.DECRYPT_MODE, key, sr ); } // main過程:我們要在這里讀入密匙,創(chuàng)建DecryptStart的 // 實例,它就是我們的定制ClassLoader。 // 設置好ClassLoader以后,我們用它裝入應用實例, // 最后,我們通過Java Reflection API調(diào)用應用實例的main方法 static public void main( String args[] ) throws Exception { String keyFilename = args[0]; String appName = args[1]; // 這些是傳遞給應用本身的參數(shù) String realArgs[] = new String[args.length-2]; System.arraycopy( args, 2, realArgs, 0, args.length-2 ); // 讀取密匙 System.err.println( "[DecryptStart: reading key]" ); byte rawKey[] = Util.readFile( keyFilename ); DESKeySpec dks = new DESKeySpec( rawKey ); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" ); SecretKey key = keyFactory.generateSecret( dks ); // 創(chuàng)建解密的ClassLoader DecryptStart dr = new DecryptStart( key ); // 創(chuàng)建應用主類的一個實例 // 通過ClassLoader裝入它 System.err.println( "[DecryptStart: loading " appName "]" ); Class clasz = dr.loadClass( appName ); // 最后,通過Reflection API調(diào)用應用實例 // 的main()方法 // 獲取一個對main()的引用 String proto[] = new String[1]; Class mainArgs[] = { (new String[1]).getClass() }; Method main = clasz.getMethod( "main", mainArgs ); // 創(chuàng)建一個包含main()方法參數(shù)的數(shù)組 Object argsArray[] = { realArgs }; System.err.println( "[DecryptStart: running " appName ".main()]" ); // 調(diào)用main() main.invoke( null, argsArray ); } public Class loadClass( String name, boolean resolve ) throws ClassNotFoundException { try { // 我們要創(chuàng)建的Class對象 Class clasz = null; // 必需的步驟1:如果類已經(jīng)在系統(tǒng)緩沖之中 // 我們不必再次裝入它 clasz = findLoadedClass( name ); if (clasz != null) return clasz; // 下面是定制部分 try { // 讀取經(jīng)過加密的類文件 byte classData[] = Util.readFile( name ".class" ); if (classData != null) { // 解密... byte decryptedClassData[] = cipher.doFinal( classData ); // ... 再把它轉(zhuǎn)換成一個類 clasz = defineClass( name, decryptedClassData, 0, decryptedClassData.length ); System.err.println( "[DecryptStart: decrypting class " name "]" ); } } catch( FileNotFoundException fnfe ) // 必需的步驟2:如果上面沒有成功 // 我們嘗試用默認的ClassLoader裝入它 if (clasz == null) clasz = findSystemClass( name ); // 必需的步驟3:如有必要,則裝入相關(guān)的類 if (resolve && clasz != null) resolveClass( clasz ); // 把類返回給調(diào)用者 return clasz; } catch( IOException ie ) { throw new ClassNotFoundException( ie.toString() ); } catch( GeneralSecurityException gse ) { throw new ClassNotFoundException( gse.toString() ); } } } |
對于未經(jīng)加密的應用,正常執(zhí)行方式如下: % java App arg0 arg1 arg2
對于經(jīng)過加密的應用,則相應的運行方式為: % java DecryptStart key.data App arg0 arg1 arg2
DecryptStart有兩個目的。一個DecryptStart的實例就是一個實施即時解密操作的定制ClassLoader;同時,DecryptStart還包含一個main過程,它創(chuàng)建解密器實例并用它裝入和運行應用。示例應用App的代碼包含在App.java、Foo.java和Bar.java內(nèi)。Util.java是一個文件I/O工具,本文示例多處用到了它。完整的代碼請從本文最后下載。
五、注意事項
我們看到,要在不修改源代碼的情況下加密一個Java應用是很容易的。不過,世上沒有完全安全的系統(tǒng)。本文的加密方式提供了一定程度的源代碼保護,但對某些攻擊來說它是脆弱的。
雖然應用本身經(jīng)過了加密,但啟動程序DecryptStart沒有加密。攻擊者可以反編譯啟動程序并修改它,把解密后的類文件保存到磁盤。降低這種風險的辦法之一是對啟動程序進行高質(zhì)量的模糊處理�;蛘�,啟動程序也可以采用直接編譯成機器語言的代碼,使得啟動程序具有傳統(tǒng)執(zhí)行文件格式的安全性。
另外還要記住的是,大多數(shù)JVM本身并不安全。狡猾的黑客可能會修改JVM,從ClassLoader之外獲取解密后的代碼并保存到磁盤,從而繞過本文的加密技術(shù)。Java沒有為此提供真正有效的補救措施。
不過應該指出的是,所有這些可能的攻擊都有一個前提,這就是攻擊者可以得到密匙。如果沒有密匙,應用的安全性就完全取決于加密算法的安全性。雖然這種保護代碼的方法稱不上十全十美,但它仍不失為一種保護知識產(chǎn)權(quán)和敏感用戶數(shù)據(jù)的有效方案。
分享:四個語句幫你提高 SQL Server 的伸縮性本文講解如何使用LEFT JOIN、CROSS JOIN以及IDENTITY值的檢索,這些技術(shù)來提高基于SQL Server的應用程序的性能或改善其可伸縮性。 你將遇到的現(xiàn)象:應用程序中的SQL 查詢不能按照您想要的方式
- sql 語句練習與答案
- 深入C++ string.find()函數(shù)的用法總結(jié)
- SQL Server中刪除重復數(shù)據(jù)的幾個方法
- sql刪除重復數(shù)據(jù)的詳細方法
- SQL SERVER 2000安裝教程圖文詳解
- 使用sql server management studio 2008 無法查看數(shù)據(jù)庫,提示 無法為該請求檢索數(shù)據(jù) 錯誤916解決方法
- SQLServer日志清空語句(sql2000,sql2005,sql2008)
- Sql Server 2008完全卸載方法(其他版本類似)
- sql server 2008 不允許保存更改,您所做的更改要求刪除并重新創(chuàng)建以下表
- SQL Server 2008 清空刪除日志文件(瞬間日志變幾M)
- Win7系統(tǒng)安裝MySQL5.5.21圖解教程
- 將DataTable作為存儲過程參數(shù)的用法實例詳解
Mssql數(shù)據(jù)庫教程Rss訂閱編程教程搜索
Mssql數(shù)據(jù)庫教程推薦
- 解讀優(yōu)化SQL Server數(shù)據(jù)庫查詢方法
- 如何查看并導出數(shù)據(jù)表中字段的注釋信息
- 查詢表里有N組相同記錄的SQL語句
- MSSQL2005在networkservice權(quán)限運行附加數(shù)據(jù)庫報(Microsoft SQL Server,錯誤: 5120)
- SQL Server 2005通用分頁存儲過程及多表聯(lián)接應用
- SQL Server 數(shù)據(jù)庫清除日志的方法
- 解讀SQL Server 2008可用性
- SQL Server 2008存儲結(jié)構(gòu)之GAM、SGAM介紹
- 談數(shù)據(jù)庫手邊系列:SQL Server數(shù)據(jù)表信息
- 解讀4個編寫SQL語句需要注意的常識
猜你也喜歡看這些
- 相關(guān)鏈接:
- 教程說明:
Mssql數(shù)據(jù)庫教程-如何有效防止Java程序源碼被人偷窺?(3)
。