Search code examples
javaandroidproguard

How to obfuscate everything but public method names and attributes with proguard?


I'm building an android framework and I need to obfuscate and shrink the jar to ship it to users.

I'm using the proguard tool included in the android SDK and I have the following requirements for the output jar:

  • keep all the classes included in the input jar, but obfuscate them.
  • don't obfuscate the class names of the classes called in the `AndroidManifest.xml
  • don't obfuscate the class name and public method names/attributes for the class that is used has an interface for the user, however do it for their contents.

To do so, I use the following configuration :

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose

-keep, allowobfuscation class com.company.*
-keepclassmembers, allowobfuscation class * {
    *;
}


-keepnames class com.company.MyClass { *; }
-keepclassmembernames class com.company.MyClass {
    public <methods>;
    public <fields>;
    #!private *; also tried this but it didn't work
}

However my private classes names and attributes still have the same name even though the content is obfuscated. Did I miss something in my wildcards?


Solution

  • After playing a bit, I found the following to be working

    -optimizationpasses 5
    -dontusemixedcaseclassnames
    -dontskipnonpubliclibraryclasses
    -dontpreverify
    -verbose
    
    -keep, allowobfuscation class com.company.*
    -keepclassmembers, allowobfuscation class * {
        *;
    }
    
    -keepnames class com.company.MyClass
    -keepclassmembernames class com.company.MyClass {
        public <methods>;
        public <fields>;
        #!private *; also tried this but it didn't work
    }
    

    The error in your configuration is the presence of { *; } at the end of the -keepnames option.

    I used the following class:

    package com.company;
    
    public class MyClass {
      public static void main(String[] args) {
        int longVariableName = publicStaticMethod();
        String abcxyz = privateStaticMethod("abc", "xyz");
        System.out.println("longVariableName: " + longVariableName);
        System.out.println("abcxyz: " + abcxyz);
      }
    
      public static int publicStaticMethod() {
        return 9000;
      }
    
      private static String privateStaticMethod(String first, String second) {
        return first + second;
      }
    }
    

    and the decompiled resulting class was this:

    package com.company;
    
    import java.io.PrintStream;
    
    public class MyClass {
      public static void main(String[] paramArrayOfString) {
        paramArrayOfString = publicStaticMethod();
        String str = a("abc", "xyz");
        System.out.println("longVariableName: " + paramArrayOfString);
        System.out.println("abcxyz: " + str);
      }
      
      public static int publicStaticMethod() {
        return 9000;
      }
      
      private static String a(String paramString1, String paramString2) {
        return paramString1 + paramString2;
      }
    }