最近在研究JAVA CLASS LOADING技術(shù),已實(shí)現(xiàn)了一個(gè)自定義的加載器。對(duì)目前自定義加載器的應(yīng)用,還在探討中。下面是自定義的CLASSLOADER在JAVA加密解密方面的一些研究。

          JAVA安全

          JAVA是解釋執(zhí)行的語言,對(duì)于不同的操作平臺(tái)都有相應(yīng)的JVM對(duì)字節(jié)碼文件進(jìn)行解釋執(zhí)行。而這個(gè)字節(jié)碼文件,也就是我們平時(shí)所看到的每一個(gè).class文件。

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

          而這個(gè)過程,在現(xiàn)在公開的網(wǎng)絡(luò)技術(shù)中,利用一個(gè)反編譯器,任何人都可以很容易的獲取它的源文件。這對(duì)于很多人來說是不希望看到的。

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

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

          利用自定義的CLASSLOADER

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

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

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

          我們加密解密的技術(shù)就應(yīng)用到這里。

          加密解密

          JAVA加密解密的技術(shù)有很多。JAVA自己提供了良好的類庫(kù)對(duì)各種算法進(jìn)行支持。對(duì)于采用哪種算法,網(wǎng)絡(luò)上說法不一,自己去GOOGLE一下吧。

          下面用DES對(duì)稱加密算法(設(shè)定一個(gè)密鑰,然后對(duì)所有的數(shù)據(jù)進(jìn)行加密)來簡(jiǎn)單舉個(gè)例子。

          首先,生成一個(gè)密鑰KEY。
          我把它保存到key.txt中。這個(gè)文件就象是一把鑰匙。誰擁有它,誰就能解開我們的類文件。代碼參考如下:
          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 {

                  
          // 創(chuàng)建一個(gè)可信任的隨機(jī)數(shù)源,DES算法需要
                  SecureRandom sr = new SecureRandom();
                  
          // 用DES算法創(chuàng)建一個(gè)KeyGenerator對(duì)象
                  KeyGenerator kg = KeyGenerator.getInstance("DES");
                  
          // 初始化此密鑰生成器,使其具有確定的密鑰長(zhǎng)度
                  kg.init(sr);
                  
          // 生成密匙
                  SecretKey key = kg.generateKey();
                  
          // 獲取密鑰數(shù)據(jù)
                  byte rawKeyData[] = key.getEncoded();
                  
          // 將獲取到密鑰數(shù)據(jù)保存到文件中,待解密時(shí)使用
                  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();
                  }


              }

          }

          第二步,對(duì)我們所要進(jìn)行加密的類文件進(jìn)行加密。

          比如我有一個(gè)DigestPass類,已經(jīng)被正常編譯好生成DigestPass.class文件。此時(shí),這個(gè)類文件是任何人都可以用的。因?yàn)橄到y(tǒng)的類加載器可以自動(dòng)的加載它。那么下一步,我們要做的就是把這個(gè)類文件加密。使系統(tǒng)的類加載器無法讀取到正確的字節(jié)碼文件。參考代碼如下:
          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算法要求有一個(gè)可信任的隨機(jī)數(shù)源
                  SecureRandom sr = new SecureRandom();
                  
          // 獲得密匙數(shù)據(jù)
                  FileInputStream fi = new FileInputStream(new File("key.txt"));
                  
          byte rawKeyData[] = new byte[fi.available()];
                  fi.read(rawKeyData);
                  fi.close();
                  
          // 從原始密匙數(shù)據(jù)創(chuàng)建DESKeySpec對(duì)象
                  DESKeySpec dks = new DESKeySpec(rawKeyData);
                  
          // 創(chuàng)建一個(gè)密匙工廠,然后用它把DESKeySpec轉(zhuǎn)換成一個(gè)SecretKey對(duì)象
                  SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(dks);
                  
          // Cipher對(duì)象實(shí)際完成加密操作
                  Cipher cipher = Cipher.getInstance("DES");
                  
          // 用密匙初始化Cipher對(duì)象
                  cipher.init(Cipher.ENCRYPT_MODE, key, sr);
                  
          // 現(xiàn)在,獲取要加密的文件數(shù)據(jù)
                  FileInputStream fi2 = new FileInputStream(new File("DigestPass.class"));
                  
          byte data[] = new byte[fi2.available()];
                  fi2.read(data);
                  fi2.close();
                  
          // 正式執(zhí)行加密操作
                  byte encryptedData[] = cipher.doFinal(data);
                  
          // 用加密后的數(shù)據(jù)覆蓋原文件
                  FileOutputStream fo = new FileOutputStream(new File("DigestPass.class"));
                  fo.write(encryptedData);
                  fo.close();
              }

          }


          第三步,用自定義的CLASSLOADER進(jìn)行加載。參考代碼如下:
          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算法要求有一個(gè)可信任的隨機(jī)數(shù)源
                  SecureRandom sr = new SecureRandom();
                  
          // 獲得密匙數(shù)據(jù)
                  FileInputStream fi = new FileInputStream(new File("key.txt"));
                  
          byte rawKeyData[] = new byte[fi.available()];// = new byte[5];
                  fi.read(rawKeyData);
                  fi.close();
                  
          // 從原始密匙數(shù)據(jù)創(chuàng)建一個(gè)DESKeySpec對(duì)象
                  DESKeySpec dks = new DESKeySpec(rawKeyData);
                  
          // 創(chuàng)建一個(gè)密匙工廠,然后用它把DESKeySpec對(duì)象轉(zhuǎn)換成一個(gè)SecretKey對(duì)象
                  SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(dks);
                  
          // Cipher對(duì)象實(shí)際完成解密操作
                  Cipher cipher = Cipher.getInstance("DES");
                  
          // 用密匙初始化Cipher對(duì)象
                  cipher.init(Cipher.DECRYPT_MODE, key, sr);
                  
          // 現(xiàn)在,獲取數(shù)據(jù)并解密
                  FileInputStream fi2 = new FileInputStream(new File("DigestPass.class"));
                  
          byte encryptedData[] = new byte[fi2.available()];
                  fi2.read(encryptedData);
                  fi2.close();
                  
          // 正式執(zhí)行解密操作
                  byte decryptedData[] = cipher.doFinal(encryptedData);
                  
          // 這時(shí)把數(shù)據(jù)還原成原有的類文件
                  
          // FileOutputStream fo = new FileOutputStream(new
                  
          // File("DigestPass.class"));
                  
          // fo.write(decryptedData);
                  
          // 用解密后的數(shù)據(jù)加載類并應(yīng)用
                  MyClassloader mcl = new MyClassloader("E:/");
                  Class cl 
          = mcl.loadClass(decryptedData, "com.neusoft.jiami.DigestPass");
                  DigestPass dp 
          = cl.newInstance();
              }

          }

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

          總結(jié)

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

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

          歡迎來訪!^.^!
          本BLOG僅用于個(gè)人學(xué)習(xí)交流!
          目的在于記錄個(gè)人成長(zhǎng).
          所有文字均屬于個(gè)人理解.
          如有錯(cuò)誤,望多多指教!不勝感激!

          Feedback

          # re: JAVA加密解密---自定義類加載器應(yīng)用  回復(fù)  更多評(píng)論   

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

          # re: JAVA加密解密---自定義類加載器應(yīng)用  回復(fù)  更多評(píng)論   

          2007-04-22 13:14 by 久城
          @kurt
          多謝指點(diǎn),已經(jīng)修改。

          # re: JAVA加密解密---自定義類加載器應(yīng)用  回復(fù)  更多評(píng)論   

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


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

          你難道還弄個(gè)加載器的加載器?

          # re: JAVA加密解密---自定義類加載器應(yīng)用  回復(fù)  更多評(píng)論   

          2007-04-23 18:37 by 久城
          @交口稱贊
          謝謝,我是這樣想的,這個(gè)方法可以使用于網(wǎng)絡(luò)加載類。密鑰文件保存在客戶端與服務(wù)器端,自定義的類加載器保存在客戶端。通過網(wǎng)絡(luò)傳輸?shù)闹挥屑用苓^的字節(jié)碼。類加載器只在本機(jī)上運(yùn)行。這樣即使被網(wǎng)絡(luò)截取到字節(jié)碼文件,也很難被反編譯。
          但是如果攻擊者能夠訪問到我的客戶端,并且取得我的類加載器的話。那我這樣加密就無效了。
          至于如何對(duì)類加載器加密?嘿嘿,我在這方面是菜菜!學(xué)習(xí)。

          # re: JAVA加密解密---自定義類加載器應(yīng)用  回復(fù)  更多評(píng)論   

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

          Copyright © 久城

          主站蜘蛛池模板: 苏尼特右旗| 阳泉市| 南川市| 宝丰县| 罗田县| 湖州市| 大港区| 泉州市| 涞源县| 临澧县| 昌都县| 体育| 界首市| 南城县| 双流县| 西平县| 胶南市| 崇阳县| 新干县| 温州市| 滦平县| 和田县| 绥宁县| 白城市| 丽江市| 汨罗市| 宁晋县| 重庆市| 吉林省| 宁南县| 香河县| 双牌县| 克拉玛依市| 道孚县| 连南| 舒城县| 苍梧县| 息烽县| 延庆县| 图们市| 泰顺县|