Mobile apps with offline features mean that code is available at any given time on someone’s mobile device. As developers, we were all taught to produce clean and readable code to keep our sanity, but this doesn’t work well when our code is available for potential exploitation. Unfortunately, it makes it easier for attackers to circumvent security measures or have access to more information than they should.

At OutSystems, we take our clients’ security concerns seriously; it is one of our top priorities. Protecting intellectual property and preventing code theft and reuse by third parties are just some of the vectors that we have to deal with.

That’s why I decided to run a few experiments on my own. I wanted to see what techniques could work to protect source code. I did some digging and realized that minification and obfuscation can be used to fill that gap, turning clean and readable code into the bloodiest code mess one can imagine, all while making your app more performant. Let’s have a look at the techniques I tried and their results.

Minification vs. Obfuscation

Although some might easily confuse both, minification and obfuscation are quite different. Following Wikipedia’s definition, minification focuses on “removing all unnecessary characters without changing the code’s functionality.”

During minification, all meaningless code is stripped (for example, whitespaces, comments) mainly reducing the file size. For applications based on JavaScript, this is probably the main advantage. Reducing file sizes means faster downloads and faster loading speeds, in other words, improving the performance of your app. The performance can be further increased when using minification with gzip compression for network transfers.

Here’s an example of a simple piece of code before and after minification:

Example of a simple function before its minification.

Example of the same function after its minification.

On the other hand, obfuscation is used to make code willfully ambiguous and harder to understand (note: this is not the same as encryption). During obfuscation, multiple statements are replaced by equivalent expressions. For example, a common use of obfuscation is splitting strings into multiple strings, like so:

Simple string before obfuscation.

Simple string after obfuscation split into three smaller strings

Simple, right? If this is not enough, you can apply more transformations to make it even harder to read by separating every character and replacing it with its hexadecimal value. Here’s what this looks like with the “Hello World” simple string:

Simple string split by character and converted into hexadecimal value

Applying multiple transformations to your code will increase its confusion and resilience, protecting your intellectual property and making it less vulnerable to code theft.

Lessons Learned

So we learned that minification removes unnecessary characters such as whitespaces and comments that don’t impact the code flow. Obfuscation transforms your code into something harder to understand without changing its logic. We also learned that using these transformations in your source code can protect it from code theft by increasing its resilience and that these are good techniques to discourage anyone trying to make some sense out of your code. There’s no bullet-proof obfuscation technique; your code will only be safe until someone with unwavering determination breaks it.

The Cost of Security

Although minification and obfuscation protect the code, they can also have their drawbacks in both file size and rendering performance. We did a couple of tests to assess the impact of applying these techniques to our code base. We were mainly focusing on how long it takes to render and the file size of an APK/IPA in the end.

Rendering Time

Having silky smooth transitions and animations is what amazes everyone who uses a mobile application, so we must absolutely be sure this isn’t affected by our changes. To try this out, I applied minification and obfuscation transformations to one of our generated applications and measured the time it took to render an animated list of 100 elements with it.

Time to render an animated list with 100 elements.
Time to render an animated list with 100 elements.

Although the time differences seem small, we can’t neglect an increase of the rendering times. Depending on what the application does and the mobile phones it is targeting, the rendering time may or may not have an impact. But in the worst case scenario, it can affect the end-user experience.

File Size

In the mobile-centric world we live in, the amount of storage available in a device is becoming less of a concern. However, file size is still a problem when the devices can easily connect to 3G or 4G networks or use pay-by-the-byte data plans. Android’s Developer page even has an article on how to reduce the APK size.

Here you can see how applying both minification and obfuscation to one of our app’s code affected the installer size.

Difference in size of the installers after applying the transformations.
Difference in size of the installers after applying the transformations.
At first look, we would think that having an increase in the file size wouldn’t be expected since we were applying minification techniques. But after further scrutiny, it actually makes sense.

Obfuscation can add a lot of unnecessary code to increase its resilience, and that’s what causes the increase in the file size. Having minification applied over it doesn’t help much since it only removes unnecessary whitespaces.

Note that these numbers are the result of applying both techniques. Had I applied them individually, I would have gotten different results.

Balancing Security and Performance

After these tests, we could conclude that because of the amount of unnecessary code, obfuscation can impact both file size and rendering time. Obviously, without neglecting the end users and to give them the best experience possible, both techniques should always be applied. Don't forget that you can choose the type of obfuscation to apply, which will directly impact the entropy you add. So it's really up to you to balance different levels of code protection and experience.

Remember that in this day and age, security is the keyword and it should always be favored. Not just to protect your end users, but also to protect your business.