JAVA software encryption - digital digest and code confusion

Keywords: Java Programming Maven xml


Because JAVA is an interpreted language, it is easy to decompile. Maybe many companies will add License verification steps to their products before they leave the factory. Is License verification really safe?

NO, people with a little JAVA experience will know to decompile your war package or jar package, and then easily find your License verification code, delete it, or directly change it to return true, and easily bypass your License verification, so the License verification can only prevent gentlemen, not villains.

So how to make your JAVA program more secure? Using digital summarization technology + code obfuscation.

It is necessary to know what digital signature is before we talk about digital summary. See Easy to understand and explain what is digital signature and digital abstract.

        With the idea of digital signature, we use digital digest to encrypt our class files. If we don't want users to modify the code related to license verification, we will LicenseCheck.class Make a HASH algorithm to calculate a HASH value (i.e. summary information). Users need to verify the summary information before using the software. If the user has modified the licensecheck . class file, then the summary information will change and the verification will fail. The specific code is as follows:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

public class CheckAspect {
	private final String POINT_CUT = "execution(public * com.founder.vt.controllers.*.*(..))";
	public void pointCut(){}

	@Before(value = "pointCut()")
	public void before(JoinPoint joinPoint){
		if(!isCracked()) {
			System.out.println("In order to ensure the integrity of the system, the system does not allow any unauthorized decompilation and modification, thank you!");
		}else {
			System.out.println("Verification passed.");
	private long crc32 =  0L;
	private boolean isCracked()
		if(crc32 == 0L)
			crc32 = getCRC32();
          	if(crc32 == 0x59416716L)     //Equivalent to the decimal 1497458454   
          		return true;
          	return false;
	private long getCRC32()
		List classList = new ArrayList();
		CRC32 crc = new CRC32();
			byte buffer[] = new byte[1024];

			int len = -1;
			BufferedInputStream bis = null;
			Iterator it = classList.iterator();
				Class clazz = (Class);
				String className = clazz.getName();
				className = className.substring(className.lastIndexOf(".") + 1);
				bis = new BufferedInputStream(clazz.getResourceAsStream(className+".class"));
				while((len =, 0, 1024)) > 0)
			return crc.getValue();
		catch(Exception ex)
			return 0;

        Verify the digital summary to prevent the code from being tampered with. It needs to cooperate with Aspect aspect programming to play its power. Because if you just add the algorithm of verify the digital summary to the code, the user can also find it easily. After decompilation, remove the code. If you use Aspect oriented programming, you can hide the Aspect logic or summary information (for example, put it in a large area In the middle of the class), making it more difficult for users to find it.

You may ask, even so, there is also the possibility of being found by users. At this time, we can come up with a magic trick: code confusion.

The principle of code confusion is to replace the package name, class name, method name and variable name in the compiled class file with meaningless a,b,c, so as to improve the code reading cost.

After confusion with Proguard, the code decompiled by JD GUI is as follows:

ps: the master who can read this kind of code is not included in our discussion!

There are two ways to confuse. Take maven project as an example to configure pom.xml As follows:

<!-- ProGuard Confusing plug-ins-->
                        <!--Confusion time, this is packaging time confusion-->
                            <!--What is the function of using plug-ins, of course, is confusion-->
                    <!--Will the generated PG File installation and deployment-->
                    <!--Confusion or not-->
                    <!--Specify build file classification-->
                        <!--JDK Target version 1.8-->
                        <option>-target 1.8</option>
                        <!--Do not shrink (remove comments, unreferenced code)-->
                        <!--No optimization (change code implementation logic)-->
                        <!--Do not pass non-public class files and members-->
                        <!--Allow access to and modification of classes and class members with modifiers during optimization-->
                        <!--Identify member names of unified obfuscation classes to increase obfuscation,Conflict prevention-->
                        <!--No case mixing class name mechanism-->
                        <!--Do not confuse all package names, Spring There are a large number of fixed write package names in the configuration-->
                        <!-- <option>-keeppackagenames</option>
                        <option>-adaptclassstrings</option> -->
                        <!--Don't confuse all special classes-->
                            -keepattributes                             Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod
                        <!--Don't confuse all set/get Methods, after all, some of the third-party frameworks used in the project (for example Shiro)A lot of set/get mapping-->
                        <option>-keepclassmembers public class *{void set*(***);*** get*();} </option>
                        <!-- Just confuse the classes under this package -->
                        <!-- <option>-keep class !com.licence.** { *; }</option> -->
                        <!-- <option>-keep class !com.util.bak.* { *; }</option> -->
                        <!-- Don't confuse the classes under this package -->
                        <option>-keep class com.controllers.* { *; }</option>
                        <option>-keep class com.mapper.* { *; }</option>
                        <!-- No confusion main method -->
                        <option>-keep class com.App { *; }</option>
                        <!--Do not display warning message, if displayed, it will appear Error Confusion cannot be completed!-->
                        <option>-dontwarn **</option>
                    <!--Add dependency, here you can modify it as you need, here the test only needs one JRE Of Runtime Just a bag-->
                    <!--The filter for loading files is your project directory-->
                    <!--What to load, here only classes Success, after all, you can't JSP Mix it up-->
                    <!--Output directory-->
                    <!--Use 6.0.2 Version to confuse-->

The above code can be used for pro testing. Generally, not all methods can be confused. For example, the interface method of controller is for the front-end to call. If it is confused, the front-end cannot call. For example, the mapping file of mabatis cannot be confused. This root can be excluded by using the - keep statement according to the situation of each project.

Of course, if you want to continue to increase the difficulty, you can write your own classloader:

Those interested in the above methods can do their own research, which is not discussed in this paper.

For children's shoes interested in JAVA software encryption and digital signature, QQ group (936800640) can be added to discuss and learn together!

Posted by fansa on Wed, 10 Jun 2020 20:54:33 -0700