Menu

ProGuard + Spring Boot application obfuscation

Help
2016-11-15
2017-01-10
  • Thiago Pereira

    Thiago Pereira - 2016-11-15

    Hi guys.
    I recently tried to obfuscate with ProGuard 5.3.1 a .jar file created with spring boot 1.4.2 framework.

    However, I am receiving the following return:

    ProGuard, version 5.3.1
    Reading program jar [/Users/thiago/Desktop/base-1.0.0.jar]
    Warning: class [BOOT-INF/classes/br/com/coderi/base/BaseApplication.class] unexpectedly contains class [br.com.coderi.base.BaseApplication]
    Warning: class [BOOT-INF/classes/br/com/coderi/base/configuration/AuthProvider.class] unexpectedly contains class [br.com.coderi.base.configuration.AuthProvider]
    Warning: class [BOOT-INF/classes/br/com/coderi/base/configuration/ServletCustomizer.class] unexpectedly contains class [br.com.coderi.base.configuration.ServletCustomizer]
    Warning: class [BOOT-INF/classes/br/com/coderi/base/configuration/WebSecurityConfiguration.class] unexpectedly contains class [br.com.coderi.base.configuration.WebSecurityConfiguration]
    Warning: class [BOOT-INF/classes/br/com/coderi/base/controller/AdviceController.class] unexpectedly contains class [br.com.coderi.base.controller.AdviceController]
    Warning: class [BOOT-INF/classes/br/com/coderi/base/controller/AgendaController.class] unexpectedly contains class [br.com.coderi.base.controller.AgendaController]
    Warning: class [BOOT-INF/classes/br/com/coderi/base/controller/CaixaController.class] unexpectedly contains class [br.com.coderi.base.controller.CaixaController]
    
    [...]
    
    Warning: class [BOOT-INF/classes/br/com/coderi/base/validation/ProfissionalValidator.class] unexpectedly contains class [br.com.coderi.base.validation.ProfissionalValidator]
    Warning: class [BOOT-INF/classes/br/com/coderi/base/validation/ServicoValidator.class] unexpectedly contains class [br.com.coderi.base.validation.ServicoValidator]
    Warning: class [BOOT-INF/classes/br/com/coderi/base/validation/UsuarioValidator.class] unexpectedly contains class [br.com.coderi.base.validation.UsuarioValidator]
    Reading library jar [/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/rt.jar]
    Warning: there were 97 classes in incorrectly named files.
             You should make sure all file names correspond to their class names.
             The directory hierarchies must correspond to the package hierarchies.
             (http://proguard.sourceforge.net/manual/troubleshooting.html#unexpectedclass)
             If you don't mind the mentioned classes not being written out,
             you could try your luck using the '-ignorewarnings' option.
    Please correct the above warnings first.
    

    This is the hierarchy of the .jar file:

    ├── BOOT-INF
    │   ├── classes
    │   │   ├── application.properties
    │   │   ├── banner.txt
    │   │   ├── br
    │   │   │   └── com
    │   │   │       └── coderi
    │   │   │           └── base
    │   │   │               ├── BaseApplication.class
    │   │   │               ├── configuration
    │   │   │               │   ├── AuthProvider.class
    │   │   │               │   ├── [...]
    │   │   │               ├── controller
    │   │   │               │   ├── [...]
    │   │   │               ├── model
    │   │   │               │   ├── [...]
    │   │   │               ├── repositories
    │   │   │               │   ├── [...]
    │   │   │               ├── services
    │   │   │               │   ├── [...]
    │   │   │               ├── utils
    │   │   │               │   ├── [...]
    │   │   │               └── validation
    │   │   │                   ├── [...]
    │   │   ├── i18n
    │   │   │   ├── messages.properties
    │   │   ├── static
    │   │   │   ├── [...]
    │   │   └── templates
    │   │       ├── [...]
    │   └── lib
    │       ├── activation-1.1.jar
    │       └── [...]
    ├── META-INF
    │   ├── MANIFEST.MF
    │   └── maven
    │       └── br.com.coderi
    │           └── base
    │               ├── pom.properties
    │               └── pom.xml
    └── org
        └── springframework
            └── boot
                └── loader
                    ├── [...]
    

    What am I doing wrong?

     
  • Eric Lafortune

    Eric Lafortune - 2016-11-15

    Hi Thiago,

    ProGuard requires that the names of the class files in a jar file correspond directly to the names of the classes, without a prefix like "BOOT-INF/classes". You should unpack the class files in a directory and provide the class root directory as input to ProGuard, e.g. "-injars /tmp/BOOT-INF/classes". When ProGuard has processed the code, you can repackage the processed classes with the proper hierarchy for Spring Boot.

    See the ProGuard manual > Troubleshooting > Warning: class file ... unexpectedly contains class ...

    Eric

     
    • Thiago Pereira

      Thiago Pereira - 2016-11-16

      Hi Erick, thanks for your answer.
      I am already extracting the classes directory to use as input in ProGuard (and apparently it's okay now), However I am not able to repackage in the spring hierarchy (when creating the .jar file, the spring structure is not maintained).

      Please, can you help me with this?

       
  • Jan-Philipp Kappmeier

    Hi Thiago,

    Spring Boot basically requires three directories, BOOT-INF, META-INF and org. Obfuscation of your own classes and repacking to a fat jar can be roughly done the following way:

    # Extract the unobfuscated fat jar from Spring Boot
    jar xvf input.jar
    
    # Execute ProGuard, as input for ProGuard use
    # -injars BOOT-INF/classes/
    java -jar proguard.jar @ proguard.conf
    
    # If you also want to obfuscate the libs, add
    # -injars BOOT-INF/lib
    # Be aware, probably needs filtering, if some but not all libs should be obfuscated. I have not tested, but I believe the Spring Framwork libraries should not be obfuscated because they would require a lot of keep exceptions in the ProGuard configuration.
    # If some of the libs should be used for obfuscation in the copy step below **remove** the libs before copying, otherwise the old files remain in the fat jar.
    
    # Copy the old files excluding the classes to a new directory.
    # First, the classes are stored here:
    mkdir obfuscated/BOOT-INF
    mkdir obfuscated/BOOT-INF/classes
    
    # I assume the output is obfuscated-classes.jar
    # It has to be extracted in the new output
    cp obfuscated-classes.jar obfuscated/BOOT-INF/classes
    pushd obfuscated/BOOT-INF/classes
    jar xvf obfuscated-classes.jar
    rm obfuscated-classes.jar
    popd
    
    # Copy the remaining files
    boot_directories=(BOOT-INF/lib META-INF org)
    for boot_directory in ${boot_directories[@]}; do
        mkdir -p "./obfuscated/$boot_directory"
    
        copy_command="cp -R ./$boot_directory/* ./obfuscated/$boot_directory/"
        eval $copy_command
    done
    
    # Finally, create a new jar
    pushd obfuscated
    # Be aware: do not use * as selector, the order of the entries in the resulting jar is important!
    jar c0mf ./META-INF/MANIFEST.MF input-obfuscated.jar BOOT-INF/classes/ BOOT-INF/lib/ META-INF/ org/
    popd
    
    # Now, there is a jar obfuscated/input-obfuscated.jar that is a Spring Boot fat jar whose BOOT-INF/classes directory is obfuscated.
    

    I hope this could help you somhow