Consider what features/functionalities
- Debug
- Release
This can leave more flexibility to future API changes without breaking the APIs exposed in earlier versions.
- Java example project
- Kotlin example project
Public interfaces
com.my.package.api
Private/Internal implementations
com.my.package.api.internal
Then for your obfuscation rules, you can have it like below:
-keep public class com.my.package.api.* { public *; }
So that only the public classes/interfaces are kept and all those ones inside com.my.package.api.internal
will be obfuscated.
Proguard is toll-free and built-in with Android.
Can apply multi-pass obfuscation if the project does obfuscation using Dexguard. Interesting features of Dexguard
- Names obfuscation
- String encryption
- Reflection
- Removing logging code and stack traces
- Native libs encryption
- Class encryption
ClassNotFoundException the application tries to access a class by means of reflection, but DexGuard has removed or obfuscated it. You should explicitly preserve the class. For example:
-keep class mypackage.MyClass
NoSuchMethodException
the application tries to access a method by means of reflection (for a WebView, for instance), but DexGuard has removed or obfuscated it. You should explicitly preserve the method. For example:
-keepclassmembers class mypackage.MyClass {
void myMethod(java.lang.String);
}
-keepparameternames
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
-renamesourcefileattribute SourceFile
-dontnote
-dontwarn
-keep
Specifies classes and class members (fields and methods) to be preserved
as entry points to your code. For example, in order to keep an application, you can specify
the main class along with its main method. In order to process a library, you should specify all
publicly accessible elements.
-keepclassmembers
Specifies class members to be preserved, if their classes are preserved as
well. For example, you may want to keep all serialization fields and
methods of classes that implement the Serializable
interface.
-flattenpackagehierarchy
Specifies to repackage all packages that are renamed, by moving them into
the single given parent package. Without argument or with an empty string
(''), the packages are moved into the root package. This option is one
example of further obfuscating package
names. It can make the processed code smaller and less comprehensible.
Only applicable when obfuscating.
-encryptclasses
-encryptstrings
-accessthroughreflection
Specifies to replace direct access to the specified classes and class
members by reflection. Matching class references are then replaced
by Class.forName constructs. Reads and writes of matching
fields are replaced by Class.getField and
Field.get/set constructs. Method invocation are replaced
by Class.getMethod and Method.invoke constructs.
For example, when processing the Android License Verification Library, you
may want to add reflection
for sensitive APIs in the Android run-time. Only applicable when
obfuscating.
-keepresourcefiles
# flow obfuscation
-obfuscatecode
# Commonly used for stripping logs.
-assumenosideeffects
# Provide a customized names dictionary, by default the dictionary style is a, b, c, d etc.
-obfuscationdictionary
-dontoptimize
-dontusemixedcaseclassnames
Library projects need to provide a proper obfuscation guide to help users integrate with their applications.
- Mockito
- Robolectric
- AndroidJUnit
- Should cover all the use case of public API
- Application update success with persistent data.
- Xposed,
- Frida,
- IDA
- CydiaSubstrate
- Java BytecodeViewer
- Not breaking API
- Apply design patterns
- Programmers’ guide
- Javadoc
- High level architecture design doc
If the library is security oriented, providing a security guideline will be meaningful to users.
- Native vs Java Always doing trade-off between security and easiness. The advantages of native layer is its difficulty of being reverse engineered. But it will be also more challenging compared to Java layer.
- Strip debug symbols.
- Compiler options for including / excluding particular modules according to functionality requirement. i.e. sqlite compiler options.
- ABIs inclusion,
consider only include the necessary ABIs, e.g.
arm64-v8a
andx86_64
which are for real devices and emulators respectively.