Java加密解密class文件,使用classLoader動態解密class文件



前言

在日常開發中,可能會遇到要對系統中比較敏感的代碼進行保護,那么下面就總結一下保護源碼的方法中最簡單的方式,即文件加密

首先,加密和解密的大致思想是:加密無非就是對class文件進行異或一下,解密呢,那就是再對class文件異或回來即可。

加密后的文件如果想要用到的話,就需要classLoader動態加載進來,具體實現請移步至:自定義ClassLoader動態加載Class文件

 

代碼實現

  1 /**
  2  * 加解密類
  3  */
  4 public class EdCipher {
  5 
  6     private String encryptFolder = "encrypt";
  7 
  8     /**
  9      * 加密方法
 10      * @param name 需要加密的文件名
 11      */
 12     public void encryptClass(String name) {
 13         String path = getFilePath(name);
 14         // classFile為待加密的class文件
 15         File classFile = new File(path);
 16         if (!classFile.exists()) {
 17            // TODO 如果文件不存在,做相應的處理。一般情況下都是拋出異常;
 18         } else {
 19            // folder 是准備在待加密的文件也就是classFIle的同級目錄下創建一個文件夾,里面放着加密后的文件
 20             File folder = new File(classFile.getParent() + File.separator + encryptFolder);
 21             if (!folder.exists()) {
 22                 folder.mkdirs();
 23             }
 24         }
 25         // cipheredClass 為加密后文件的全路徑文件名
 26         String cipheredClass = classFile.getParent() + File.separator + encryptFolder + File.separator + classFile.getName();
 27         try (
 28                 FileInputStream fileInputStream = new FileInputStream(classFile);
 29                 BufferedInputStream bis = new BufferedInputStream(fileInputStream);
 30                 FileOutputStream fileOutputStream = new FileOutputStream(cipheredClass);
 31                 BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream)
 32         ) {
 33             int data;
 34             while ((data = bis.read()) != -1) {
 35                 bos.write(data ^ 0xFF);
 36             }
 37             bos.flush();
 38         } catch (IOException e) {
 39             e.printStackTrace();
 40         }
 41 
 42         // 現在將原來未加密的文件刪除
 43         classFile.delete();
 44         
 45         //下面這一句在文件后面加了一個“en”,最后生成的文件就是xxx.classen,這樣做的目的是為了在啟動服務器的時候
 46         //tomcat會自動檢查classespath下的class文件,如果我不加上一個“en”,那么改加密文件就會被tomcat掃描到。
 47         //如果被掃描到了,但是它又是一個被加密后的文件,頭部信息被修改了,那么tomcat就會報錯,啟動不起來。這算是一個小技巧。
 48         File oldFile = new File(path + "en");
 49         if (oldFile.exists()) {
 50             oldFile.delete();
 51         }
 52         File cipheredFile = new File(cipheredClass);
 53         cipheredFile.renameTo(oldFile);
 54         cipheredFile.getParentFile().delete();
 55     }
 56 
 57     /**
 58      * 解密方法
 59      * @param name 需要解密的文件名
 60      */
 61     protected byte[] decryptClass(String name) {
 62         String path;
 63         if (!name.contains(".class")) {
 64             path = getDefFilePath(name);
 65         } else {
 66             path = name;
 67         }
 68         File encryptedClassFile = new File(path);
 69         if (!encryptedClassFile.exists()) {
 70             System.out.println("decryptClass() File:" + path + " not found!");
 71             return null;
 72         }
 73         byte[] result = null;
 74         BufferedInputStream bis = null;
 75         ByteArrayOutputStream bos = null;
 76         try {
 77             bis = new BufferedInputStream(new FileInputStream(encryptedClassFile));
 78             bos = new ByteArrayOutputStream();
 79             int data;
 80             while ((data = bis.read()) != -1) {
 81                 bos.write(data ^ 0xFF);
 82             }
 83             bos.flush();
 84             result = bos.toByteArray();
 85         } catch (Exception e) {
 86             e.printStackTrace();
 87         } finally {
 88             try {
 89                 if (bis != null) {
 90                     bis.close();
 91                 }
 92                 if (bos != null) {
 93                     bos.close();
 94                 }
 95             } catch (IOException e) {
 96                 e.printStackTrace();
 97             }
 98         }
 99         return result;
100     }
101 
102    //獲取加密前文件的絕對路徑
103     private String getFilePath(String name) {
104         String path;
105         String str = name.substring(name.lastIndexOf(".") + 1, name.length()) + ".class";
106         path = EdCipher.class.getResource(str).toString();
107         path = path.substring(path.indexOf("file:/") + "file:/".length(), path.length());
108         if (System.getProperty("os.name").toUpperCase().contains("LINUX")) {
109             path = File.separator + path;
110         }
111         return path;
112     }
113 
114    //獲取加密后文件的絕對路徑 
115     private String getDefFilePath(String name) {
116         String path;
117         String str = name.substring(name.lastIndexOf(".") + 1, name.length()) + ".classen";
118         path = EdCipher.class.getResource(str).toString();
119         path = path.substring(path.indexOf("file:/") + "file:/".length(), path.length());
120         return path;
121     }
122 
123    // 測試
124     public static void main(String[] args) {
125         EdCipher edCipher = new EdCipher();
126         edCipher.encryptClass(args[0]);
127     }
128 }

 

如果要想在Ant打包的時候,就加密文件,就需要在build.xml配置文件中調用該類的Main方法即可

1 <!-- 加密 -->
2 <target name="encrypt">
3     <java classname="EdCipher" failonerror="true">
4         <classpath refid="classpath.run"/>
5         <arg line="需要加密的文件的包名+文件名"/>
6     </java>
7 </target>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM