JAVA加密解密---自定義類加載器應用

          Posted on 2007-04-22 11:09 久城 閱讀(4987) 評論(5)  編輯  收藏 所屬分類: Java理解筆記
          最近在研究JAVA CLASS LOADING技術,已實現了一個自定義的加載器。對目前自定義加載器的應用,還在探討中。下面是自定義的CLASSLOADER在JAVA加密解密方面的一些研究。

          JAVA安全

          JAVA是解釋執行的語言,對于不同的操作平臺都有相應的JVM對字節碼文件進行解釋執行。而這個字節碼文件,也就是我們平時所看到的每一個.class文件。

          這是我們大家都知道的常識,也就是由.java文件,經過編譯器編譯,變成JVM所能解釋的.class文件。

          而這個過程,在現在公開的網絡技術中,利用一個反編譯器,任何人都可以很容易的獲取它的源文件。這對于很多人來說是不希望看到的。

          對于加密解密技術,我懂的不多,有些可以利用某種技術“模糊”JAVA類文件。這樣能夠使反編譯的難度增加。但估計反編譯器的技術水平也在不斷提升,導致這種方法層層受阻。另外還有很多其他的技術也可以實現對JAVA文件的加密解密。我現在所想要研究的,就是其中的一種。

          JAVA的靈活性使反編譯變得容易,同時,也讓我們的加密解密的方法變得靈活。

          利用自定義的CLASSLOADER

          參照:http://www.aygfsteel.com/realsmy/archive/2007/04/18/111582.html

          JAVA中的每一個類都是通過類加載器加載到內存中的。對于類加載器的工作流程如下表示:
          1.searchfile()
          找到我所要加載的類文件。(拋除JAR包的概念,現在只是要加載一個.class文件)
          2.loadDataClass()
          讀取這個類文件的字節碼。
          3.difineClass()
          加載類文件。(加載的過程其實很復雜,我們現在先不研究它。)

          從這個過程中我們能很清楚的發現,自定義的類加載能夠很輕松的控制每個類文件的加載過程。這樣在第二步(loadDataClass)和第三步(difineClass)之間,我們將會有自己的空間靈活的控制這個過程。

          我們加密解密的技術就應用到這里。

          加密解密

          JAVA加密解密的技術有很多。JAVA自己提供了良好的類庫對各種算法進行支持。對于采用哪種算法,網絡上說法不一,自己去GOOGLE一下吧。

          下面用DES對稱加密算法(設定一個密鑰,然后對所有的數據進行加密)來簡單舉個例子。

          首先,生成一個密鑰KEY。
          我把它保存到key.txt中。這個文件就象是一把鑰匙。誰擁有它,誰就能解開我們的類文件。代碼參考如下:
          package com.neusoft.jiami;

          import java.io.File;
          import java.io.FileOutputStream;
          import java.security.SecureRandom;
          import javax.crypto.KeyGenerator;
          import javax.crypto.SecretKey;

          class Key {

              
          private String keyName;

              
          public Key(String keyName) {
                  
          this.keyName = keyName;
              }


              
          public void createKey(String keyName) throws Exception {

                  
          // 創建一個可信任的隨機數源,DES算法需要
                  SecureRandom sr = new SecureRandom();
                  
          // 用DES算法創建一個KeyGenerator對象
                  KeyGenerator kg = KeyGenerator.getInstance("DES");
                  
          // 初始化此密鑰生成器,使其具有確定的密鑰長度
                  kg.init(sr);
                  
          // 生成密匙
                  SecretKey key = kg.generateKey();
                  
          // 獲取密鑰數據
                  byte rawKeyData[] = key.getEncoded();
                  
          // 將獲取到密鑰數據保存到文件中,待解密時使用
                  FileOutputStream fo = new FileOutputStream(new File(keyName));
                  fo.write(rawKeyData);
              }


              
          public static void main(String args[]) {
                  
          try {
                      
          new Key("key.txt");
                  }
           catch (Exception e) {
                      e.printStackTrace();
                  }


              }

          }

          第二步,對我們所要進行加密的類文件進行加密。

          比如我有一個DigestPass類,已經被正常編譯好生成DigestPass.class文件。此時,這個類文件是任何人都可以用的。因為系統的類加載器可以自動的加載它。那么下一步,我們要做的就是把這個類文件加密。使系統的類加載器無法讀取到正確的字節碼文件。參考代碼如下:
          package com.neusoft.jiami;

          import java.io.File;
          import java.io.FileInputStream;
          import java.io.FileOutputStream;
          import java.security.SecureRandom;

          import javax.crypto.Cipher;
          import javax.crypto.SecretKey;
          import javax.crypto.SecretKeyFactory;
          import javax.crypto.spec.DESKeySpec;

          public class JiaMi {

              
          public static void main(String[] args) throws Exception {

                  
          // DES算法要求有一個可信任的隨機數源
                  SecureRandom sr = new SecureRandom();
                  
          // 獲得密匙數據
                  FileInputStream fi = new FileInputStream(new File("key.txt"));
                  
          byte rawKeyData[] = new byte[fi.available()];
                  fi.read(rawKeyData);
                  fi.close();
                  
          // 從原始密匙數據創建DESKeySpec對象
                  DESKeySpec dks = new DESKeySpec(rawKeyData);
                  
          // 創建一個密匙工廠,然后用它把DESKeySpec轉換成一個SecretKey對象
                  SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(dks);
                  
          // Cipher對象實際完成加密操作
                  Cipher cipher = Cipher.getInstance("DES");
                  
          // 用密匙初始化Cipher對象
                  cipher.init(Cipher.ENCRYPT_MODE, key, sr);
                  
          // 現在,獲取要加密的文件數據
                  FileInputStream fi2 = new FileInputStream(new File("DigestPass.class"));
                  
          byte data[] = new byte[fi2.available()];
                  fi2.read(data);
                  fi2.close();
                  
          // 正式執行加密操作
                  byte encryptedData[] = cipher.doFinal(data);
                  
          // 用加密后的數據覆蓋原文件
                  FileOutputStream fo = new FileOutputStream(new File("DigestPass.class"));
                  fo.write(encryptedData);
                  fo.close();
              }

          }


          第三步,用自定義的CLASSLOADER進行加載。參考代碼如下:
          package com.neusoft.jiami;

          import java.io.File;
          import java.io.FileInputStream;
          import java.io.FileOutputStream;
          import java.security.SecureRandom;

          import javax.crypto.Cipher;
          import javax.crypto.SecretKey;
          import javax.crypto.SecretKeyFactory;
          import javax.crypto.spec.DESKeySpec;
          import com.neusoft.classloader.MyClassLoader;

          public class JieMi {

              
          public static void main(String[] args) throws Exception {

                  
          // DES算法要求有一個可信任的隨機數源
                  SecureRandom sr = new SecureRandom();
                  
          // 獲得密匙數據
                  FileInputStream fi = new FileInputStream(new File("key.txt"));
                  
          byte rawKeyData[] = new byte[fi.available()];// = new byte[5];
                  fi.read(rawKeyData);
                  fi.close();
                  
          // 從原始密匙數據創建一個DESKeySpec對象
                  DESKeySpec dks = new DESKeySpec(rawKeyData);
                  
          // 創建一個密匙工廠,然后用它把DESKeySpec對象轉換成一個SecretKey對象
                  SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(dks);
                  
          // Cipher對象實際完成解密操作
                  Cipher cipher = Cipher.getInstance("DES");
                  
          // 用密匙初始化Cipher對象
                  cipher.init(Cipher.DECRYPT_MODE, key, sr);
                  
          // 現在,獲取數據并解密
                  FileInputStream fi2 = new FileInputStream(new File("DigestPass.class"));
                  
          byte encryptedData[] = new byte[fi2.available()];
                  fi2.read(encryptedData);
                  fi2.close();
                  
          // 正式執行解密操作
                  byte decryptedData[] = cipher.doFinal(encryptedData);
                  
          // 這時把數據還原成原有的類文件
                  
          // FileOutputStream fo = new FileOutputStream(new
                  
          // File("DigestPass.class"));
                  
          // fo.write(decryptedData);
                  
          // 用解密后的數據加載類并應用
                  MyClassloader mcl = new MyClassloader("E:/");
                  Class cl 
          = mcl.loadClass(decryptedData, "com.neusoft.jiami.DigestPass");
                  DigestPass dp 
          = cl.newInstance();
              }

          }

          這樣,我們就完成了類的加密解密。這個過程留給我們修改的空間還很多。我也在理解過程中。

          總結

          自定義的類加載器能夠靈活的控制類的加載過程。從而可以實現一些我們所要的功能。

          但是,即使是這樣的加密技術,對于某些高手來說,依然是脆弱的。我們所需要做的就是,理解這其中的過程,掌握這樣的技術,最終能夠應用到我們自己的實際項目中來。

          歡迎來訪!^.^!
          本BLOG僅用于個人學習交流!
          目的在于記錄個人成長.
          所有文字均屬于個人理解.
          如有錯誤,望多多指教!不勝感激!

          Feedback

          # re: JAVA加密解密---自定義類加載器應用  回復  更多評論   

          2007-04-22 13:06 by kurt
          DES是對稱加密算法不是公鑰加密算法

          # re: JAVA加密解密---自定義類加載器應用  回復  更多評論   

          2007-04-22 13:14 by 久城
          @kurt
          多謝指點,已經修改。

          # re: JAVA加密解密---自定義類加載器應用  回復  更多評論   

          2007-04-23 15:07 by 交口稱贊
          類加載器本身怎么辦


          別人反編譯你的類加載器,
          然后用你的類加載器去解密。。。

          你難道還弄個加載器的加載器?

          # re: JAVA加密解密---自定義類加載器應用  回復  更多評論   

          2007-04-23 18:37 by 久城
          @交口稱贊
          謝謝,我是這樣想的,這個方法可以使用于網絡加載類。密鑰文件保存在客戶端與服務器端,自定義的類加載器保存在客戶端。通過網絡傳輸的只有加密過的字節碼。類加載器只在本機上運行。這樣即使被網絡截取到字節碼文件,也很難被反編譯。
          但是如果攻擊者能夠訪問到我的客戶端,并且取得我的類加載器的話。那我這樣加密就無效了。
          至于如何對類加載器加密?嘿嘿,我在這方面是菜菜!學習。

          # re: JAVA加密解密---自定義類加載器應用  回復  更多評論   

          2007-04-25 18:08 by liji
          hello kitty! :D

          Copyright © 久城

          主站蜘蛛池模板: 巴东县| 灵宝市| 青浦区| 浦县| 洞口县| 青阳县| 富民县| 成安县| 平遥县| 满洲里市| 布尔津县| 涿鹿县| 赞皇县| 晴隆县| 灌阳县| 扎赉特旗| 峨边| 沾益县| 明水县| 绥棱县| 桐梓县| 慈溪市| 威宁| 逊克县| 商洛市| 昌邑市| 嘉义县| 蕲春县| 凉山| 正镶白旗| 西峡县| 双峰县| 永宁县| 卓资县| 宁乡县| 泸州市| 九龙坡区| 临武县| 临湘市| 怀宁县| 砀山县|