使用Xjar對jar文件進行加密,防止反編譯


軟件簡介

XJar — Spring-Boot JAR 包加密運行工具,避免源碼泄露以及反編譯。

Spring Boot JAR安全加密運行工具,同時支持原生的JAR。

基於對JAR包內資源的加密以及拓展ClassLoader來構建的一套程序加密啟動,動態解密運行的方案,避免源碼泄露或反編譯。

功能特性

  • 無需侵入代碼,只需要把編譯好的JAR包通過工具加密即可。

  • 完全內存解密,杜絕源碼以及字節碼泄露以及反編譯。

  • 支持所有JDK內置加解密算法。

  • 可選擇需要加解密的字節碼或其他資源文件,避免計算資源浪費。

環境依賴-廢話不多說,直接上源碼。新建項目

配置pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com</groupId>
    <artifactId>xjar-encrype</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 設置 jitpack.io 倉庫 -->
    <repositories>
        <repository>
            <id>jitpack.io</id>
            <url>https://jitpack.io</url>
        </repository>
    </repositories>

    <!-- 添加 XJar 依賴 -->
    <dependencies>
        <dependency>
            <groupId>com.github.core-lib</groupId>
            <artifactId>xjar</artifactId>
            <version>v2.0.6</version>
        </dependency>
    </dependencies>


</project>

  寫代碼

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.Date;

import static io.xjar.agent.hibernate.XjarTest.encryptJarDangerMode;

public class UserSwing {

    public static void main(String[] args) {
        // 創建 JFrame 實例
        JFrame frame = new JFrame("Jar加密,防止反編譯");
        // Setting the width and height of frame
        frame.setSize(600, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        /* 創建面板,這個類似於 HTML 的 div 標簽
         * 我們可以創建多個面板並在 JFrame 中指定位置
         * 面板中我們可以添加文本字段,按鈕及其他組件。
         */
        JPanel panel = new JPanel();
        // 添加面板
        frame.add(panel);
        /*
         * 調用用戶定義的方法並添加組件到面板
         */
        placeComponents(panel);

        // 設置界面可見
        frame.setVisible(true);
    }

    private static void placeComponents(final JPanel panel) {

        /* 布局部分我們這邊不多做介紹
         * 這邊設置布局為 null
         */
        panel.setLayout(null);

        // 創建 需要加密的jar JLabel
        JLabel fromLabel = new JLabel("選擇需要加密的jar:");
        fromLabel.setBounds(10,20,120,25);
        panel.add(fromLabel);

        /*
         * 用於記錄未加密jar的文本域
         */
        final JTextField fromText = new JTextField(20);
        fromText.setBounds(140,20,210,25);
        panel.add(fromText);

        // 創建選擇按鈕
        JButton fromButton = new JButton("選擇...");
        fromButton.setBounds(360, 20, 80, 25);
        panel.add(fromButton);


        // 加密后jar要保存的位置
        JLabel toLabel = new JLabel("選擇需要保存的位置");
        toLabel.setBounds(10,50,120,25);
        panel.add(toLabel);

        /*
         *文本域用於記錄保存路徑
         */
        final JTextField toText = new JTextField(20);
        toText.setBounds(140,50,210,25);
        panel.add(toText);

        // 創建選擇按鈕
        JButton toButton = new JButton("選擇...");
        toButton.setBounds(360, 50, 80, 25);
        panel.add(toButton);


        // 輸入密碼的文本域
        JLabel passwordLabel = new JLabel("加密密碼:");
        passwordLabel.setBounds(10,80,80,25);
        panel.add(passwordLabel);

        /*
         * 這個類似用於輸入的文本域
         * 但是輸入的信息會以點號代替,用於包含密碼的安全性
         */
        final JPasswordField passwordText = new JPasswordField(20);
        passwordText.setBounds(100,80,165,25);
        panel.add(passwordText);

        // 創建登錄按鈕
        JButton startButton = new JButton("開始");
        startButton.setBounds(10, 110, 80, 25);
        panel.add(startButton);

        //日志顯示框
        final JTextArea textArea = new JTextArea("");
        textArea.setBounds(10,150,300,150);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        panel.add(textArea);

        /*
         * 選擇jar按鈕監聽事件
         */
        fromButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {  //按鈕點擊事件
                JFileChooser chooser = new JFileChooser();             //設置選擇器
                chooser.setMultiSelectionEnabled(false);             //設為單選
                int returnVal = chooser.showOpenDialog(null);        //是否打開文件選擇框
                if (returnVal == JFileChooser.APPROVE_OPTION) {          //如果符合文件類型
                    String filepath = chooser.getSelectedFile().getAbsolutePath();      //獲取絕對路徑
                    if (!".jar".equals(filepath.substring(filepath.length()-4))) {
                        JOptionPane.showMessageDialog(null, "文件格式不正確,請選擇jar文件!", "文件格式錯誤", JOptionPane.ERROR_MESSAGE);
                    } else {
                        fromText.setText(filepath);
                    }
                    System.out.println(filepath);
                }
            }
        });

        /*
         * 選擇加密后jar保存路徑按鈕監聽事件
         */
        toButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {  //按鈕點擊事件
                JFileChooser chooser = new JFileChooser();             //設置選擇器
                chooser.setMultiSelectionEnabled(false);             //設為單選
                chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); //設置只選目錄
                chooser.setDialogTitle("選擇加密后jar保存位置");
                int returnVal = chooser.showOpenDialog(null);        //是否打開文件選擇框
                if (returnVal == JFileChooser.APPROVE_OPTION) {          //如果符合文件類型
                    String filepath = chooser.getSelectedFile().getAbsolutePath();      //獲取絕對路徑
                    toText.setText(filepath);
                    System.out.println(filepath);
                }
            }
        });

        /*
         * 選擇開始徑按鈕的監聽事件
         */
        startButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                String fromJarPath = fromText.getText();
                String toJarPath = toText.getText() + "\\encrypt" + getNowDateTime() + ".jar";
                String password = new String(passwordText.getPassword());
                System.out.println("fromJarPath=" + fromJarPath);
                System.out.println("toJarPath=" + toJarPath);
                System.out.println("password=" + password);
                if (fromJarPath != null && !"".equals(fromJarPath)) {
                    if (toJarPath != null && !"\\encrypt".equals(toJarPath.substring(0,8))) {
                        if (password != null && !"".equals(password)) {
                            //打印輸入日志
                            StringBuilder builder = new StringBuilder();
                            builder.append("fromJarPath=" + fromJarPath + "\n")
                                    .append("toJarPath=" + toJarPath + "\n") ;
                            textArea.setText(builder.toString());
                            //開始加密文件
                            encryptJarDangerMode(fromJarPath,toJarPath,password);
                            textArea.append("jar加密成功!\n請測試接口是否正常(注意:Swagger不可用)");
                        } else {
                            JOptionPane.showMessageDialog(null, "請輸入加密的密碼!", "密碼不能為空!", JOptionPane.ERROR_MESSAGE);
                        }
                    } else {
                        JOptionPane.showMessageDialog(null, "保存路徑不能為空!", "保存路徑不能為空!", JOptionPane.ERROR_MESSAGE);
                    }
                } else {
                    JOptionPane.showMessageDialog(null, "jar文件不能為空!", "jar文件不能為空!", JOptionPane.ERROR_MESSAGE);
                }

            }
        });
    }

    /**
     * 獲取當前格式化時間的方法
     * @return
     */
    private static String getNowDateTime() {
        String dateNow = "";
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        Date date = new Date();
        dateNow = format.format(date);
        return dateNow;
    }
}

  直接將項目main運行 如下圖

 

 當然還有直接了當的方法哦

import io.xjar.XConstants;
import io.xjar.XKit;
import io.xjar.boot.XBoot;
import io.xjar.key.XKey;

/**
 * @description jar包加密
 * jar加密后,大小會翻倍,同時swagger無法訪問,接口暫時未發現問題
 */
public class XjarTest {

    public static void main(String[] args) {
        // Spring-Boot Jar包加密
        String password = "adas";
        String fromJarPath = "F:\\old-0.0.1-SNAPSHOT.jar";
        String toJarPath = "F:\\new.jar";
        encryptJarDangerMode(fromJarPath, toJarPath, password);
    }

    /**
     * jar包加密,防止反編譯
     * 此編譯方式在運行jar包時需要輸入密碼
     * 運行方式一 :
     *      // 命令行運行JAR 然后在提示輸入密碼的時候輸入密碼后按回車即可正常啟動
     *      java -jar /path/to/encrypted.jar
     * 運行方式二:
     *      // 也可以通過傳參的方式直接啟動,不太推薦這種方式,因為泄露的可能性更大!
     *      java -jar /path/to/encrypted.jar --xjar.password=PASSWORD
     * 運行方式三:
     *      // 對於 nohup 或 javaw 這種后台啟動方式,無法使用控制台來輸入密碼,推薦使用指定密鑰文件的方式啟動
     *      nohup java -jar /path/to/encrypted.jar --xjar.keyfile=/path/to/xjar.key
     *      xjar.key 文件說明:
     *      格式:
     *          password: PASSWORD
     *          algorithm: ALGORITHM
     *          keysize: KEYSIZE
     *          ivsize: IVSIZE
     *          hold: HOLD
     *      參數說明:
     *          password 	密碼 	無 	密碼字符串
     *          algorithm 	密鑰算法 	AES 	支持JDK所有內置算法,如AES / DES ...
     *          keysize 	密鑰長度 	128 	根據不同的算法選取不同的密鑰長度。
     *          ivsize 	向量長度 	128 	根據不同的算法選取不同的向量長度。
     *          hold 	是否保留 	false 	讀取后是否保留密鑰文件。
     * @param fromJarPath 需要加密的jar
     * @param toJarPath 加密后的jar
     * @param password 加密密碼
     */
    public static void encryptJar(String fromJarPath, String toJarPath, String password) {

        try {
            // Spring-Boot Jar包加密
            XKey xKey = XKit.key(password);
            XBoot.encrypt(fromJarPath, toJarPath, xKey);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * jar包解密
     * @param fromJarPath 已通過Xjar加密的jar文件路徑
     * @param toJarPath 解密后的jar文件
     * @param password 密碼
     */
    public static void decryptJar(String fromJarPath, String toJarPath, String password) {
        try {
            XKey xKey = XKit.key(password);
            XBoot.decrypt(fromJarPath, toJarPath, xKey);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * jar包危險加密模式
     * 即不需要輸入密碼即可啟動的加密方式,這種方式META-INF/MANIFEST.MF中會保留密鑰,請謹慎使用!
     * @param fromJarPath 需要加密的jar
     * @param toJarPath 加密后的jar
     * @param password 加密密碼
     */
    public static void encryptJarDangerMode(String fromJarPath, String toJarPath, String password) {
        try {
            XKey xKey = XKit.key(password);
            XBoot.encrypt(fromJarPath, toJarPath, xKey, XConstants.MODE_DANGER);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

  jar包下載不下來可配置maven私服

      <mirror>
          <id>alimaven</id>
          <mirrorOf>central,!jitpack.io</mirrorOf>
          <name>aliyun maven</name>
          <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
      </mirror>

  一個命令解決maven依賴下載失敗后無法重新下載依賴的問題-請到本地maven下執行該cmd命令

for /r %i in (*.lastUpdated) do del %i

  

剩下的你懂的哦~

請一鍵三連···

 


免責聲明!

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



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