Resource Encryption in PreEmptive Protection™ DashO™ encrypts resources packaged in an app or library, making it more difficult to copy or alter them. During the build, DashO encrypts the resources with AES (a symmetric encryption algorithm) and injects code to decrypt them in the running app. We currently support encrypting both assets and raw resources.
You can enable/disable and configure Resource Encryption on the Resource Encryption pages of the DashO GUI.
NOTE: This feature is only available in Android Mode.
How it Works
Currently Resource Encryption is supported for Android using Android Mode and the Gradle integration with the DashO Gradle Plugin for Android. APK post-processing and Gradle integrations using the DashO Gradle Plugin for Java are not supported.
The Gradle build will automatically add an
encryptResources task that will, if Resource Encryption is enabled, encrypt the selected resources.
This step will encrypt resources for each of the build variants for which DashO is enabled.
For each build variant, DashO will only encrypt the resources that are part of that build variant.
The original resource files are not modified by the encryption process.
When DashO protects the application or library code, additional code is injected that will decrypt the resources when accessed by the running app.
A class named
Wrapper$Secrets containing the secret key is also added during this step.
It is critically important to enable R8 minification and to enable String Encryption for this class, to ensure that the secret key is not found easily.
The DashO Gradle Plugin for Android generates the secret key that is used for encryption of the resources and decryption at run-time. This key is passed to DashO in an environment variable to avoid accidental disclosure in log files or process lists.
APIs and Behavior
We currently support encrypting assets and raw resources that are accessed via
Support is provided by wrapping
InputStreams that access encrypted resources with an
InputStream implementation that decrypts the data.
DashO automatically injects code to decrypt streams produced by the following method calls:
Some libraries that the Android Gradle Plugin includes as inputs to DashO contain calls to these methods.
This includes compatibility libraries that might have classes under the
androidx packages, but does not include anything in
Any APIs in these libraries that delegate reading of resources to these methods are supported by Resource Encryption.
Review the DashO build output with
debug enabled to see exactly what method calls are wrapped by Resource Encryption.
If any resources are accessed in a way other than these, they will need to be excluded from encryption. If a resource that is not encrypted is accessed by a call that is wrapped with decryption code, the data will be passed through unmodified.
If a resource that is encrypted is accessed by a call that is not wrapped with decryption code, the result is undefined. For data formats that have their own consistency checks, the app will likely throw a format exception. For other formats, interpreting an encrypted file may cause undefined behavior.
Resource Encryption protects both assets and raw resources. Protection of these two types of resources can be enabled/disabled independently. The DashO GUI provides an interface for configuring include and exclude rules for assets and raw resources. There is no provision for controlling where decryption code is injected other than Global Processing Exclusions which prevent DashO from making any changes to selected classes.
If you have a library sub-project which contains resources, you can can configure the
libraryResourceDirs properties to encrypt those resources.
Library (AAR) projects are also supported, however there may be issues if they are protected again in an Application using DashO's resource encryption.
When building the library project, the decryption classes must be configured to be renamed by R8.
excludeFromProtection feature should be used to exclude the library from additional processing by DashO when including that library in an application.
Applications cannot directly access encrypted resources from an AAR. If your library provides resources to applications, those resources should either be excluded from encryption or accessed via APIs provided by the library.
You should test the performance of your app or library with and without Resource Encryption. Decryption is a processor-bound activity. Expect some decreases in run-time performance if Resource Encryption is enabled. Excluding less sensitive files from Resource Encryption can be used to mitigate performance costs, if necessary.
In our testing, an image loading test-app ran roughly 30% slower when processing encrypted resources.
The test-app read
.png images from persistent storage, and then decoded them with
Loading 18 images roughly 2 MB in size each took:
- 1.1 seconds without Resource Encryption
- 1.4 seconds with Resource Encryption
Testing was done on a Pixel XL running Android 10.