Protecting your Java Code - JWCrypt
When you invest time into writing a commercial app that you need to sell to keep your business alive, you need to have some way to protect that investment.
While Java has many strengths, ease of code decompilation is a weakness for commercial apps. Decrypting a standard Java application is a very simple matter and can be done with free tools available on the internet.
Obfuscators make this process more difficult and can offer some protection against full decompilation and source code theft but typically don't offer significant protection against licensing workarounds, nor do they protect sensitive resources.
For commercial apps where your investment is at stake, something stronger is required.
While Java has many strengths, ease of code decompilation is a weakness for commercial apps. Decrypting a standard Java application is a very simple matter and can be done with free tools available on the internet.
Obfuscators make this process more difficult and can offer some protection against full decompilation and source code theft but typically don't offer significant protection against licensing workarounds, nor do they protect sensitive resources.
For commercial apps where your investment is at stake, something stronger is required.
JWCrypt AES Code Encryption
JWCrypt is baked into JWrapper. If you use JWrapper then protecting your JARs and other resources is as simple as adding protected="yes" to any <File> tags.
Unlike other less scrupulous vendors though we don't claim that JWCrypt provides you with AES-level protection of your code. Neither do we claim that pure obfuscation or compilation to native code (toted as a cure-all but actually merely another form of obfuscation) provides a final answer to these issues.
To crack AES encryption is computationally infeasible. For all intents and purposes it is therefore impossible to crack today and in the forseeable future. The problem though is that if your app is AES encrypted then how does the Operating System run it? Put simply, there is always a route to run your app, and therefore always a route to potentially decompile and access your app.
Without this route your app would not be able to run. It is a theoretical impossibility to protect your app against any attack and yet still have it be runnable by the operating system.
This situation its not quite as bad as it sounds. Being a theoretical impossibility doesn't mean it has to be easy, and this is where JWCrypt focuses its efforts.
Unlike other less scrupulous vendors though we don't claim that JWCrypt provides you with AES-level protection of your code. Neither do we claim that pure obfuscation or compilation to native code (toted as a cure-all but actually merely another form of obfuscation) provides a final answer to these issues.
To crack AES encryption is computationally infeasible. For all intents and purposes it is therefore impossible to crack today and in the forseeable future. The problem though is that if your app is AES encrypted then how does the Operating System run it? Put simply, there is always a route to run your app, and therefore always a route to potentially decompile and access your app.
Without this route your app would not be able to run. It is a theoretical impossibility to protect your app against any attack and yet still have it be runnable by the operating system.
This situation its not quite as bad as it sounds. Being a theoretical impossibility doesn't mean it has to be easy, and this is where JWCrypt focuses its efforts.
The Best Feasible Protection
When we designed JWCrypt we knew that it would never be impossible to circumvent, so we focused on two key goals:
We don't claim, unlike many JAR encryption providers, to use AES encryption to give your app the same level of protection as an AES-encrypted file with a secret key, instead we use AES to give AES-level protection against a wide range of typical attacks and to reduce the attack surface to a minimum, known path.
This known path is then designed to be easy for Java to run, but difficult in the extreme for anyone to decompile and follow. Java can run through this extremely complex path and launch your app in less than half a second. But for an attacker to progressively decompile tens of layers of self-enclosed decryption class bundles to finally get through to your class, all the while circumventing safety checks, is a very long, very difficult, very tedious and very demoralising process.
It is not theoretically impossible, but having designed and implemented the entire system, we would hate to have to try to decompile anything protected by JWCrypt.
- Use AES encryption to reduce the attack surface to an absolute bare minimum.
- Make the path to decompiling your app as long, difficult, demoralising and tedious as possible.
We don't claim, unlike many JAR encryption providers, to use AES encryption to give your app the same level of protection as an AES-encrypted file with a secret key, instead we use AES to give AES-level protection against a wide range of typical attacks and to reduce the attack surface to a minimum, known path.
This known path is then designed to be easy for Java to run, but difficult in the extreme for anyone to decompile and follow. Java can run through this extremely complex path and launch your app in less than half a second. But for an attacker to progressively decompile tens of layers of self-enclosed decryption class bundles to finally get through to your class, all the while circumventing safety checks, is a very long, very difficult, very tedious and very demoralising process.
It is not theoretically impossible, but having designed and implemented the entire system, we would hate to have to try to decompile anything protected by JWCrypt.
Protecting your investment in the best way possible
If you have valuables in your home or at your office, there may be no theoretically impenetrable way to protect them, but you are far better off keeping them hidden, protected in a safe, behind locked doors in a secure building than in a cardboard box on the street. There is no silver bullet solution to the problem of protecting your code, but to do nothing to protect your investment is to give it away from day one to anyone who asks.
Native compilers and other obfuscators are not a cure-all
Native Java compilers are compilers that compile Java classes to native code. These are often touted as being the 'gold standard' for code protection.
In reality though, native compilers simply translate your code from one language into another. There is no programming language on earth that is impenetrable so you essentially remain in exactly the same position. At best, your code has been obfuscated. This is not a bad thing, it does offer some protection, but it is not the gold standard of protection for your code.
Native compilers also incur other problems such as their inability to use standard JVMs leading to a need to fully test your app on all operating systems to verify that the custom JVM works in the way expected for your app.
Standard (free) Java code obfuscators provide a similar service directly on your Java app but let you run with standard JVMs. These Java code obfuscators can be used in conjunction with JWCrypt to provide an even higher level of protection.
In reality though, native compilers simply translate your code from one language into another. There is no programming language on earth that is impenetrable so you essentially remain in exactly the same position. At best, your code has been obfuscated. This is not a bad thing, it does offer some protection, but it is not the gold standard of protection for your code.
Native compilers also incur other problems such as their inability to use standard JVMs leading to a need to fully test your app on all operating systems to verify that the custom JVM works in the way expected for your app.
Standard (free) Java code obfuscators provide a similar service directly on your Java app but let you run with standard JVMs. These Java code obfuscators can be used in conjunction with JWCrypt to provide an even higher level of protection.
The need to protect your resources as well as your source code
Often the focus in protecting investments in commercial apps revolves entirely around the source code. This is the obvious case since without any protection for your source code you have no way to license your app. However, protecting the source code often does not protect the licensing of your app. Regardless of the language your app is translated into - compiled Java, natively compiled C or anything else - if your licensing code is trivially decompiled then your licensing is no longer effective.
Obfuscation, through native compilation or through Java obfuscators, can provide some protection for your source code but it does not protect your licensing code and resources.
JWCrypt allows you to mark resources included in your build for protection in the same way as you protect your Java JAR files. The resources are AES encrypted with a key known only to your app so without going through the one long path to decompilation the only alternative is to mount a futile attack against AES encryption.
Obfuscation, through native compilation or through Java obfuscators, can provide some protection for your source code but it does not protect your licensing code and resources.
JWCrypt allows you to mark resources included in your build for protection in the same way as you protect your Java JAR files. The resources are AES encrypted with a key known only to your app so without going through the one long path to decompilation the only alternative is to mount a futile attack against AES encryption.
Recognising and avoiding typical attacks
The typical arguments against JAR encryption is that it is disingenuous to suggest that your app is protected to the same level as an AES encrypted file with a secret key, and that modifications to the JVM libraries provide an easy route to decompilation.
Neither of these arguments apply.
With a single layer of encryption it is possible to decrypt the decryptor and get access to the sensitive code. Likewise with no layers of protection and checks against these types of attack it is again possible to mount an attack by modifying JVM libraries. JWCrypt's multiple layers of encryption and security checks help protect against these types of attacks, resulting in the decryption of useless distracting code and not your app's code and resources.
Neither of these arguments apply.
With a single layer of encryption it is possible to decrypt the decryptor and get access to the sensitive code. Likewise with no layers of protection and checks against these types of attack it is again possible to mount an attack by modifying JVM libraries. JWCrypt's multiple layers of encryption and security checks help protect against these types of attacks, resulting in the decryption of useless distracting code and not your app's code and resources.
Using JWCrypt when producing Apps with JWrapper
To use JWrapper to protect your JARs or any other resources you need only add protected='yes' to any <File> tag in your JWrapper XML file.
The entire JAR will then be encrypted and JWrapper will handle the rest. Any resources that are included in an encrypted JAR file can be loaded in exactly the same way (e.g. Class.getResourceAsStream() etc) and JWrapper will efficiently decrypt these on the fly from the encrypted JAR archive they are stored in.
If you have marked other individual resources outside of a JAR file for encryption then your app can load them using the JWCrypt API. Loading via this methods also works when your app has not been encrypted or is running outside of JWrapper to facilitate testing.
The entire JAR will then be encrypted and JWrapper will handle the rest. Any resources that are included in an encrypted JAR file can be loaded in exactly the same way (e.g. Class.getResourceAsStream() etc) and JWrapper will efficiently decrypt these on the fly from the encrypted JAR archive they are stored in.
If you have marked other individual resources outside of a JAR file for encryption then your app can load them using the JWCrypt API. Loading via this methods also works when your app has not been encrypted or is running outside of JWrapper to facilitate testing.
Using JWCrypt as standalone JAR protection
To use JWCrypt for standalone JAR protection you first need to download the JWrapper JAR file from our download section.
You can then add your jwlicense.txt in the same folder as your downloaded jwrapper jar and use the command line to run JWCrypt as follows:
java -jar jwrapper-xxxx.jar jwcrypt [jvmrestrictions] <company ID> <jar1> <jar2> ...
- Company ID will be used to prefix the protected jars, so you should make this something short and without any spaces or special characters.
- JVM Restrictions will instruct JWrapper to apply restrictions on the JVM that includes your jar files to avoid the use of agents which aid in decompilation.
For example to protect one jar without jvm restrictions:
java -jar jwrapper-0123456789.jar jwcrypt mycompany mySourceJar.jar
And to protect multiple jars with jvm restrictions enabled:
java -jar jwrapper-0123456789.jar jwcrypt jvmrestrictions mycompany mySource1.jar mySource2.jar mySource3.jar
Based on your configuration, after processing has completed, JWCrypt will print a full list of instructions on how to run your jar as a standalone file or how to include it as a third party library. In both cases JVM-level arguments and classpath additions will be required.
You can then add your jwlicense.txt in the same folder as your downloaded jwrapper jar and use the command line to run JWCrypt as follows:
java -jar jwrapper-xxxx.jar jwcrypt [jvmrestrictions] <company ID> <jar1> <jar2> ...
- Company ID will be used to prefix the protected jars, so you should make this something short and without any spaces or special characters.
- JVM Restrictions will instruct JWrapper to apply restrictions on the JVM that includes your jar files to avoid the use of agents which aid in decompilation.
For example to protect one jar without jvm restrictions:
java -jar jwrapper-0123456789.jar jwcrypt mycompany mySourceJar.jar
And to protect multiple jars with jvm restrictions enabled:
java -jar jwrapper-0123456789.jar jwcrypt jvmrestrictions mycompany mySource1.jar mySource2.jar mySource3.jar
Based on your configuration, after processing has completed, JWCrypt will print a full list of instructions on how to run your jar as a standalone file or how to include it as a third party library. In both cases JVM-level arguments and classpath additions will be required.