This is a Android Gradle plugin that obfuscates strings in Kotlin classes
You have to apply the Obfustring plugin to the project.
Warning
Starting from JDK 9, string concatenation uses invokedynamic instruction by default. For this reason, the Obfustring plugin must use StringConcatFactory strategies, which use the old method of string concatenation via StringBuilder.
If you are developing a big project, you may encounter significant performance issues compared to the optimized invokedynamic instruction
buildscript {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
dependencies {
classpath("io.github.c0nnor263:obfustring-plugin:$version")
}
}
plugins {
id("com.android.application") version *** apply false
}
plugins {
id("com.android.application")
id("io.github.c0nnor263.obfustring-plugin")
}
obfustring {
/**
* Key used to obfuscate strings
*/
key = "exampleKey"
/**
* Configure obfustring mode using [ObfustringMode]
*/
mode = ObfustringMode.DEFAULT
/**
* Enable logging
*/
loggingEnabled = true
/**
* Set JVM argument -Xstring-concat using [StringConcatStrategy]
*/
stringConcatStrategy = StringConcatStrategy.INDY
/**
* List of classes that should be excluded from obfuscation
*/
excludeClasses: List<ExcludedClassInfo> = emptyList()
/**
* Custom Obfustring implementation
*/
customObfustring: CommonObfustring = Obfustring
}
Note
For more information check source code of ObfustringExtension
- Annotation
@ObfustringThis
is used to mark classes that should be obfuscated
@ObfustringThis
class MyApplication
- Annotation
@ObfustringExclude
is used to mark classes that should not be obfuscated. This is useful whenObfustringExtension.mode
is set toObfustringMode.FORCE
@ObfustringExclude
class MyApplication
- To exclude some classes by their annotations, prefix, suffix, or whole name, you can configure
ObfustringExtension.excludeClasses
obfustring {
excludeClasses = listOf(
ExcludedClassInfo(
name = "com.example.exampleapp.AwesomeExampleClass",
prefixName = "Awesome",
suffixName = "Class",
annotations = listOf(
ExcludedClassInfo(
name = "com.example.exampleapp.ExampleAnnotation",
// ...
)
)
)
)
}
Tip
If you want to obfuscate all classes, you can edit the plugin configuration and
set mode = Obfustring.FORCE
@ObfustringThis
class MyApplication : Application() {
companion object {
private const val TAG = "MyApplication"
val username = "user#${Random.nextInt()}"
val onCreateMsg = "Hello world and $username!"
}
override fun onCreate() {
super.onCreate()
val userChecker = UserChecker()
val isValidUserMsg =
if (userChecker.isValidName(username)) {
onCreateMsg
} else {
"$username is not valid user name"
}
Log.i(
TAG,
"Application onCreate: $isValidUserMsg",
)
}
}
@Suppress("DEPRECATION")
@ObfustringThis
class UserChecker {
companion object {
@Deprecated("This is a deprecated list")
private val forbiddenNames = listOf("admin", "root", "user")
}
fun isValidName(name: String): Boolean {
return when {
name.isBlank() -> false
name.isEmpty() -> false
forbiddenNames.contains(name) -> false
else -> true
}.also { result ->
Log.i(
"TAG",
"\tisValidName: $name is $result\n" +
"\tAll forbidden names: $forbiddenNames",
)
}
}
}
public final class MyApplication extends Application {
public static final C0501a Companion = new Object();
private static final String TAG = "MyApplication";
private static final String onCreateMsg;
private static final String username;
static {
String m398a = AbstractC0520b.m398a("wgqs#");
AbstractC0700e.f1984a.getClass();
String str = m398a + AbstractC0700e.f1985b.mo0a().nextInt();
username = str;
onCreateMsg = AbstractC0520b.m398a("Dsxmq kbszl bra ") + str + AbstractC0520b.m398a("!");
}
@Override // android.app.Application
public void onCreate() {
String str;
super.onCreate();
UserChecker userChecker = new UserChecker();
String str2 = username;
if (userChecker.isValidName(str2)) {
str = onCreateMsg;
} else {
str = str2 + AbstractC0520b.m398a(" kg zpv jnmwl vwbr zpxi");
}
Log.i(AbstractC0520b.m398a("ImGqrzvdobjsk"), AbstractC0520b.m398a("Wdbmkqnuwwo skWdtlxe: ") + str);
}
}
public final class UserChecker {
public static final C0502b Companion = new Object();
private static final List<String> forbiddenNames;
static {
List<String> asList = Arrays.asList(AbstractC0520b.m398a("cryjp"), AbstractC0520b.m398a("tcau"), AbstractC0520b.m398a("wgqs"));
AbstractC0577a.m287k(asList, "asList(...)");
forbiddenNames = asList;
}
public final boolean isValidName(String str) {
AbstractC0577a.m286l(str, AbstractC0520b.m398a("poyf"));
boolean z = false;
if (!AbstractC0175d.m958Z(str) && str.length() != 0 && !forbiddenNames.contains(str)) {
z = true;
}
String m398a = AbstractC0520b.m398a("PIM");
String m398a2 = AbstractC0520b.m398a("\tkgBbnwqIouf: ");
String m398a3 = AbstractC0520b.m398a(" kg ");
String m398a4 = AbstractC0520b.m398a("\n\tWzx gqfojrlfr kaytd: ");
List<String> list = forbiddenNames;
Log.i(m398a, m398a2 + str + m398a3 + z + m398a4 + list);
return z;
}
}
If you want to write your own implementation of Obfustring encoding and decoding logic, you should open this guide
If you have any questions or suggestions, please feel free to open an issue. I will be happy to make your using of the plugin more comfortable and enjoyable.
We welcome contributions to this project! To get started, please read our Contribution guidelines
Copyright 2024 Boichuk Oleh
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.