Practical part: how to mix up encryption with springboot (proguard+xjar)

1, Background

The core code module of the project team is deployed on the user server. Another company obtained the root password of the server. The conventional way of encrypting the database by configuring environment variables and directly throwing jar packages to the server is very likely to lead to data disclosure and code disclosure.

2, Code obfuscation

1. Common confusion tools

Software nameReasons for recommendation
Allatori Java ObfuscatorLightweight can be integrated into IDE tools and introduced through configuration files
DashO for Android and JavaCharge, integrate with eclipse, prevent Java programs from being reverse engineered and tampered with, and compress the amount of code
Zelix KlassMasterIt can read and modify Java class files, and can run on any platform that supports Java virtual machine version 1.1.6.
Cinnabar CannerProtect your code from reverse engineering decompilation by creating a native Windows executable file (EXE file). This executable file contains all encrypted versions of your application classes and resources. It is only in an unencrypted state when it is called into memory by the JVM
Jmangle Java class crusherTo prevent decompiling Java programs and reduce pirated software, developers can use it to smash symbols in class files.
RetroGuardThe general bytecode obfuscator is used to seamlessly integrate into your daily construction and testing process, making it safer for you to work hard to write valuable Java code
JODEJava package with Java decoder and optimizer
ProGuardFree Java class file compression, optimization, mixer. It removes useless classes, fields, methods, and properties. Maximize bytecode optimization by renaming classes, fields, and methods with short, meaningless names. eclipse has integrated Proguard.
Java bytecode manipulation framework ASMASM is a Java bytecode manipulation framework. It can dynamically generate stub classes or other proxy classes directly in binary form, or dynamically modify classes when loading. ASM provides functions similar to toolkits such as BCEL and SERP, but it is designed to be smaller and faster, which makes it suitable for real-time code instrumentation

After comparison, proguard was finally selected. The main reasons for choosing this tool are as follows:

  • Support direct integration within pom
  • Configuration files can be integrated into pom or configured separately
  • There are many related blog introductions
  • Other project teams of the company have experience in using this

2. Actual configuration of Proguard

Taking springboot single application as an example, based on the original project configuration file, the relevant configuration of plugins needs to be modified

  • [optional] modify the Maven plugin configuration of springboot

    <!--Springboot repackage pack-->
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <executions>
            <execution>
                <!-- springboot Packaging needs repackage Otherwise, it is not executable jar -->
                <goals>
                    <goal>repackage</goal>
                </goals>
                <configuration>
                    <mainClass>com.xxx.xxx.MainApplication</mainClass>
                </configuration>
            </execution>
        </executions>
    </plugin>
    
  • [required] configure proguard

    <!-- proguard Obfuscate plug-ins-->
    <plugin>
        <groupId>com.github.wvengen</groupId>
        <artifactId>proguard-maven-plugin</artifactId>
        <version>2.2.0</version>
        <executions>
            <execution>
                <!-- It began to mix up when packing-->
                <phase>package</phase>
                <goals>
                    <goal>proguard</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <injar>${project.build.finalName}.jar</injar>
            <!--Exported jar-->
            <outjar>${project.build.finalName}.jar</outjar>
            <!-- Is it confused-->
            <obfuscate>true</obfuscate>
            <options>
    			<!--appoint java Version number-->
                <option>-target 1.8</option> 
    			<!--It is on by default, without shrinkage (delete comments and unreferenced codes)-->
                <option>-dontshrink</option> 
    			<!--It is on by default, and bytecode level optimization is turned off here-->
                <option>-dontoptimize</option>
    			<!--After confusing the class name, use Class.forName('className')And so on-->
                <option>-adaptclassstrings</option>
    			<!-- ignore warn news,If prompted org.apache.http.* If there is a problem with the class in this package, add the following code:-keep class org.apache.http.** { *; }    -dontwarn org.apache.http.**-->
                <option>-ignorewarnings</option>
                <option>-keep class org.apache.logging.log4j.util.* { *; }</option>
                <option>-dontwarn org.apache.logging.log4j.util.**</option>
    			<!--For exceptions and annotation information runtime Keep it, otherwise it will affect springboot start-up-->
                <option>-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod</option>
                <!--Don't confuse all interface Interface, optional-->
                <!--<option>-keepnames interface **</option>-->
    			<!--Keep enumeration members and methods-->
                <option>-keepclassmembers enum * { *; }</option>
    			<!--Package name-->
                <option>-keeppackagenames com.xxx.controller.**</option>
                <option>-keeppackagenames com.xxx.entity.**</option>
    			<!--Reserved method parameter name-->
                <option>-keepparameternames</option>
                <option>-keepclasseswithmembers public class * {
                    public static void main(java.lang.String[]);}
                </option> <!--retain main Class of method and its method name-->
                <option>-keepclassmembers public class * {void set*(***);*** get*();}</option>
                <!--ignore note Message, if prompted javax.annotation If there is a problem, add the following code-->
                <option>-dontnote javax.annotation.**</option>
                
                <option>-dontnote sun.applet.**</option>
                <option>-dontnote sun.tools.jar.**</option>
                <option>-dontnote org.apache.commons.logging.**</option>
                <option>-dontnote javax.inject.**</option>
                <option>-dontnote org.aopalliance.intercept.**</option>
                <option>-dontnote org.aopalliance.aop.**</option>
                <option>-dontnote org.apache.logging.log4j.**</option>
    
                <!--The entry program class cannot be confused, which will lead to springboot Can't start-->
    			<option>-keep class com.xxx.MainApplication</option>
    			<option>-keep class org.apache.logging.log4j.util.*  {*;}</option>
                
                <option>-keep class com.xxx.entity.* {*;}</option>
                <option>-keep class com.xxx.config.* {*;}</option>
                <option>-keep class com.xxx.controller.*.* {*;}</option>
                <option>-keep class com.xxx.service.kafka.* {*;}</option>
                <option>-keep class com.xxx.service.xxljob.* {*;}</option>
    
                <option>-keep interface * extends * { *; }</option>
                <option>-keep interface com.xxx.entity.*.*.* {*;}</option>
                <!--Do not confuse all classes,Save the original defined comments-->
                <option>-keepclassmembers class * {
                    @org.springframework.beans.factory.annotation.Autowired *;
                    @org.springframework.beans.factory.annotation.Value *;
                    @com.xxl.job.core.handler.annotation.XxlJob *;
                    @org.springframework.kafka.annotation.KafkaListener *;
                    }
                </option>
            </options>
            <libs>
                <!-- Add dependency java8-->
                <lib>${java.home}/lib/rt.jar</lib>
                <lib>${java.home}/lib/jce.jar</lib>
            </libs>
        </configuration>
    
    
        <dependencies>
            <!-- https://mvnrepository.com/artifact/net.sf.proguard/proguard-base -->
            <dependency>
                <groupId>net.sf.proguard</groupId>
                <artifactId>proguard-base</artifactId>
                <version>6.1.1</version>
            </dependency>
        </dependencies>
    </plugin>
    

3, Profile encryption

Jasypt is used to encrypt the configuration file

Reference configuration:

[java information security (19) encryption tool Jasypt](https://www.cnblogs.com/bjlhx/p/12229296.html)

4, jar package encryption

Jar package encryption is carried out by Xjar. The way of custom compilation is widely used for configuration on the Internet. If you want to simplify it, you can encrypt it directly through the generated jar. The following methods are not applicable to the programs developed by springBoot+jpa(hibernate) technology.

1. Custom compilation

Xjar: the spring boot jar package encrypts the running tool to avoid source code disclosure and decompilation

2. Encrypt directly through existing jar s

  1. GitHub download xjar demo, download address: https://github.com/yumingzhu/xjarDemo/tree/master/target

  2. Under the pom peer directory of your own code, create a new folder (such as xjarEncode), and add xjardemo-1.0-snapshot Jar copy put in

  3. Compile confused code, pom Command window execution under XML: mvn clean package -DskipTests

  4. Create a bat script file (such as encode.bat) in the folder created in step 2 to facilitate subsequent rapid execution

    [123456] user defined password. Fill in according to your own needs

    [targets-0.0.1-SNAPSHOT.jar] name of the jar package generated by maven packaging

    [targets.jar] name of target jar package

    java -cp .\xjarDemo-1.0-SNAPSHOT.jar XjarDemo 123456 ..\target\targets-0.0.1-SNAPSHOT.jar .\targets.jar
    
  5. implement

    1. windows execution method

      java -jar xxx.jar
      

      Enter the password you set in step 4 in the pop-up window

    2. linux execution method, create a new encode Key file

      password: 123456
      hold: true
      

      Profile description:

      Parameter nameParameter meaningdefaultexplain
      passwordpasswordnothingPassword string
      algorithmKey algorithmAESSupport all built-in algorithms of JDK, such as AES/DES
      keysizeKey length128Choose different secret key lengths according to different algorithms
      ivsizeVector length128Choose different vector lengths according to different algorithms
      holdWhether to keepfalseWhether to keep the key file after reading, true/1/yes/y, which means that it will not be deleted after reading
    3. Modify the startup script and add --xjar keyfile=encode. Key parameter. If linux is used, the following startup script is recommended to realize start / stop / restart operations

      #!/bin/bash
      #################################################################
      # Author: Shi San
      # Time: July 14, 2022
      # Purpose: start management
      #################################################################
      if [ -f /etc/init.d/functions ]; then 
          . /etc/init.d/functions
      fi
      
      
      #################################################################
      # Define variables
      #################################################################
      # application name
      SERVICE_NAME='custom'
      SERVICE_PACKAGE="${SERVICE_NAME}.jar"
      # application path
      SERVICE_PATH='custom'
      
      
      
      #################################################################
      # Define commands
      #################################################################
      function START_COMMAND()
      {
          echo "${SERVICE_PATH}/${SERVICE_PACKAGE}"
          java -Duser.timezone=Asia/Shanghai -Xms4g -Xmx4g -jar ${SERVICE_PATH}/${SERVICE_PACKAGE} --xjar.keyfile=encode.key  2>/dev/null 1>&2 &
          if [[ $? -eq 0 ]]; then
              action "${SERVICE_NAME} start successed" /bin/true
          else
              action "${SERVICE_NAME} start failed" /bin/false
          fi
      }
      
      function STOP_COMMAND()
      {
          SERVICE_PID=`ps -ef | grep "${SERVICE_PACKAGE}" | grep -v 'grep' | awk '{print $2}'`
          if [[ ${SERVICE_PID} == '' ]]; then
              action "${SERVICE_NAME} is not running" /bin/false
          else
              kill -9 ${SERVICE_PID} >/dev/null 2>&1
              if [[ $? -eq 0 ]]; then
                  action "${SERVICE_NAME} stop successed" /bin/true
              else
                  action "${SERVICE_NAME} stop failed" /bin/false
              fi
          fi
      }
      
      function STATUS_COMMAND()
      {
          SERVICE_PID=`ps -ef | grep "${SERVICE_PACKAGE}" | grep -v 'grep' | awk '{print $2}'`
          if [[ ${SERVICE_PID} == '' ]]; then
              action "${SERVICE_NAME} is not running" /bin/false
          else
              action "${SERVICE_NAME} is running" /bin/true
          fi
      }
      
      
      #################################################################
      # Define commands
      #################################################################
      case "$1" in
          start)
              START_COMMAND
              ;;
          stop)
              STOP_COMMAND
              ;;
          restart|reload)
              STOP_COMMAND
              START_COMMAND
              ;;
          status)
              STATUS_COMMAND
              ;;
          *)
              echo "Usage: $0 {start|stop|restart|status|reload}"
              ;;
      esac
      
    4. Add jar, encode Key, copy the script file to the corresponding directory of the server

    5. Execute sh xxx sh restart

5, Contrast effect before and after

1. Before confusion

2. After confusion

At this time, the configuration file and ORM mybatis xml file have not been encrypted

3. After encryption

6, Reference

  1. Summarize 10 commonly used encryption obfuscation software
  2. Count the five commonly used Java code obfuscators!
  3. There are 18 Java code obfuscation and encryption open source software
  4. proguard official website
  5. ProGuard most complete confusion rule description
  6. jar package encryption ----- xjar

Tags: Java Back-end Spring Boot

Posted by teamatomic on Fri, 15 Jul 2022 04:59:27 +0930