String Encryption is the process by which PreEmptive Protection™ DashO™ replaces strings in the constant pools of processed classes with encrypted values that are then decrypted in the running application, making it more difficult to read the string constants via static analysis of the code. This both offers a layer of protection to sensitive strings and otherwise makes it more difficult to understand the software. For instance, with String Encryption an attacker cannot easily locate the string constant for a specific message to find where it is used.
You can enable/disable and configure String Encryption on the String Encryption - Options page of the DashO GUI.
Use Removal With String Encryption
String Encryption alone protects most strings, but inlined string constants are not always fully protected. The Java compiler inlines string constants, effectively copying them into the places where they are used. DashO does not encrypt the original field values, because this could produce incorrect behavior, e.g. breaking the value of a library API constant that is used by an external application.
This means that some string constants will remain in place, unencrypted, after String Encryption. If these string constants will not be used by external applications then they can be safely removed. Therefore, to protect those string constants, configure DashO to remove unused members. Inlined string constant references will not mark the defining field as "used".
For libraries, specify
Remove if not public; otherwise specify
Remove if not public, public strings will not be removed, so any strings that require protection should not be public.
The effect of these settings can be adjusted by excluding classes, methods, or fields from Removal.
There are also size and performance costs to using String Encryption, and it may be necessary to exclude methods or classes from it. Because of inlining, both the class that defines a string constant and all of the classes that reference it must be protected with String Encryption for all copies of that string to be encrypted.
String Encryption and Reflection in Android Mode
In Android Mode, Renaming and Removal are handled by R8, while String Encryption is handled by DashO. On its own, R8 is able to detect some classes accessed via reflection and exclude them from Renaming and Removal.
However, DashO's String Encryption can prevent R8 from recognizing class names in String literals. This can cause R8 to remove or rename classes loaded via reflection, causing errors at runtime. To prevent these errors, either:
- Add R8
-keeprules to prevent the classes that are loaded via reflection from being removed or renamed, or:
- Exclude methods that contain reflection calls from String Encryption so that R8 can detect classes loaded by these calls.
You can also use
-adaptclassstringswith R8 to allow R8 to rename these classes and update String literals accordingly.
You can configure the following settings on the String Encryption - Options page of the DashO GUI.
If you configure string encryption include/exclude rules at the method-level, in some cases strings reused by methods with different rules may not be encrypted as expected.
String Encryption Level
The String Encryption Level, on a scale from 1 to 10, controls the strength and performance of the encryption and decryption algorithms. A higher level will have stronger encryption but will take longer at runtime to decrypt, potentially slowing down the application. The default level is "2".
Number of Decrypters
You can control the number of decrypters that will be generated and added to classes included in each output. The names and signatures of the methods are randomly selected (except when using an input map file). The default number of decrypters is "2".
For unmerged outputs, the number of decrypters created will be multiplied by number of inputs. If you want decrypters to be placed globally (not kept internal to the jars where they are used) add a User Property named
INJECT_DECRYPTERS_GLOBALLYand set it to
true. If this property is set, the configured number of decrypters will divided among the outputs, not added to each output.
Decrypters are always placed globally in Android Mode.
intern() should be called on strings before returning them from the injected string decrypter.
intern() method makes sure that equal strings are only represented once in memory.
If Intern Strings is turned off, any protected code, including library code, that uses
==for string comparison may return false when comparing values from equal strings. You should always use
==when comparing strings.
You can control to which classes may serve as outer classes for the generated anonymous static inner classes that will house the decrypters. You can specify the following criteria for these classes:
- Packages that these classes must not be chosen from
- Modifiers such as
publicthat these classes must match
- A regular expression, glob pattern, or name that the class's name must match
By default, DashO will exclude all
android. packages and will only include
If you specify name criteria, the decrypters will be injected based on that criteria and will be used without regards to jar boundaries.
String Encryption Map Files
If you are using Incremental Obfuscation, it is important that DashO is capable of reproducing the decrypters used when the initial obfuscation took place. Otherwise, the new obfuscated code may not interoperate properly with previously obfuscated code. A String Encryption Map File is used to document which decrypters were placed and where they were placed in a previous run of DashO.
On the String Encryption - Options page of the DashO GUI you can specify both a location of an input map file and a location for an output map file. If an output map file location is specified, then DashO will produce a String Encryption map file containing information about the decrypters produced during that build. If an input map file is specified, then DashO will reproduce the string decrypters described in the map file, and will ignore settings for the String Encryption Level and the Number of Decrypters.
String Encryption Map Files are not supported in Android Mode.
Includes and Excludes
You can set rules to determine where String Encryption is applied. String Encryption has a cost in terms of size and runtime performance, so you may want to apply it only to more sensitive parts of your application. You can specify String Encryption Includes and Excludes on the String Encryption - Include and String Encryption - Exclude pages of the DashO GUI. If no includes are specified, DashO will apply String Encryption to all methods not covered by an exclude rule. If any include rules are defined, then DashO will apply String Encryption only to included methods.
You can specify custom encryption and decryption methods for DashO to use in place of its default String Encryption. See Custom Encryption for details.