Using R8 "full mode" causes issues (workaround provided)

Issue #518 resolved
Matt King created an issue

When including the library on an Android build that has R8 “full mode” enabled, two issues arise when using minification and obfuscation:

Tink causes a failed gradle build with the error:

Caused by: com.android.tools.r8.utils.b: Missing class com.google.crypto.tink.subtle.XChaCha20Poly1305 (referenced from: byte[] com.nimbusds.jose.crypto.impl.XC20P.decryptAuthenticated(javax.crypto.SecretKey, byte[], byte[], byte[], byte[]))

This is corrected by excluding tink-android module from the dependency and including a later version manually:

    implementation(Libs.nimbus_jose_jwt) {
        exclude(group = "com.google.crypto.tink", module = "tink-android")
    }
    implementation("com.google.crypto.tink:tink-android:1.9.0")

Perhaps the tink dependency could be updated in the library?

When the library is using JSONObjectUtils to parse JSON it causes a crash at runtime in a minified/obfuscated build:

java.lang.IllegalStateException: TypeToken must be created with a type argument: new TypeToken<...>() {}; When using code shrinkers (ProGuard, R8, ...) make sure that generic signatures are preserved.

This is fixed by adding into proguard rules (in my Android app):

-keep class com.nimbusds.jose.shaded.gson.reflect.TypeToken { *; }
-keep class * extends com.nimbusds.jose.shaded.gson.reflect.TypeToken

(This was a bit tricky as I didn’t realise that it was shaded!)

Hoping this could be either documented for everyone else or fixed in the library - happy to make a PR if there is any direction you could point me to make proper updates.

Comments (11)

  1. Vladimir Dzhuvinov
    • changed status to open

    Thanks Matt for the report.

    The Tink dep was bumped to 1.9.0: ed63ee23 (but this is the general Java dep, not the -android-)

    On the second issue, the pom.xml and the README.md say the GSon is shaded. If there is a way to "inform" Proguard via some file, field or annotation in the JAR of this fact we'll do it. Just let me know. I'm not familiar with the tool.

  2. Matt King reporter

    The Tink dep was bumped to 1.9.0:

    Great! That was quick! That should work for the Android dep as well.

    On the second issue, the pom.xml and the README.md say the GSon is shaded.

    Thanks for pointing that out, I wasn’t familiar with shaded functionality in maven (I think probably because I mainly live in Android land 😅)

    If there is a way to "inform" Proguard via some file,

    As far as I know there isn’t a way to provide proguard rules to a consumer of a JAR. In Android specifically there is a way, by packaging as an AAR…though I imagine it would be extra maintenance for questionable value.

    One possibility to fix this issue altogether is to update JSONObjectUtils to use a concrete class instead of an abstract anonymous TypeToken - again happy to take a look and make a PR if needed.

    Otherwise, if the README could be updated with something like the following, it might help future users of gradle and proguard users:

    Gradle/Proguard/R8 Users

    When using proguard, ensure that the following is added to your proguard rules file:

    -keep class com.nimbusds.jose.shaded.gson.reflect.TypeToken { *; }
    -keep class * extends com.nimbusds.jose.shaded.gson.reflect.TypeToken
    

    NB: The Gson dependency is shaded, so the package namespace differs from the Gson package namespace.

  3. Vladimir Dzhuvinov

    Hi Matt!

    One possibility to fix this issue altogether is to update JSONObjectUtils to use a concrete class instead of an abstract anonymous TypeToken - again happy to take a look and make a PR if needed.

    If a code change will fix this feel free to submit a patch and we’ll publish it

    Else we’ll do plan B (the doc update).

  4. Matt King reporter

    If a code change will fix this feel free to submit a patch and we’ll publish it

    I gave it a go with a small change, but it seems I can’t get the local setup working properly some unrelated tests fail (even before I made any changes to anything). Would like to generate a jar with the changes locally to see if it makes a fix, but unclear how to do that…

  5. Vladimir Dzhuvinov

    The tests fail because another PR (merged) needs additional changes / fixes.

    You can skip the tests with mvn clean package -DskipTests :)

  6. Matt King reporter

    Alright, that got me on the right track. I’m unable to make a PR directly, so I forked the repository and made a commit.

    https://bitbucket.org/mattking2/nimbus-jose-jwt/commits/9c51ef5a15b4b470e311d51b16f156996d15a584

    This removes the need to use the extra Gson proguard rules and all works as expected 🙌

    As for the other issue related to tink - I took out the bit where I excluded it and included the newer version, but I still get the missing class com.google.crypto.tink.subtle.XChaCha20Poly1305 - even though the library has the newest version.

    Including tink-android on the Android side fixes this issue, but it’s seems like a hacky workaround. I’m not sure how to fix this issue…

    There were also a couple of annotations that R8 couldn’t find, these didn’t pop up when using the latest release, so not sure if this is a result of how I built the jar locally 🤔

    net.jcip.annotations.Immutable

    net.jcip.annotations.ThreadSafe

  7. Vladimir Dzhuvinov

    Thanks Matt, the change is now in master: feca058f

    About the Tink issue, do you have the dep explicitly imported in your projects? The Nimbus lib declares the dep as optional, so that it doesn’t get automatically pulled as dep, unless you are going to use the Tink ciphers, in which case you’ll need an explicit dep declaration.

    <dependency>
                <groupId>com.google.crypto.tink</groupId>
                <artifactId>tink</artifactId>
                <version>1.9.0</version>
                <optional>true</optional>
            </dependency>
    

  8. Matt King reporter

    Hi Vladimir,

    Great to see those changes in master 💪

    We don’t explicitly import tink on our project, so really I think the fix here is for consumers of the library with proguard and R8 full mode to ignore these missing classes:

    -dontwarn net.jcip.annotations.Immutable
    -dontwarn net.jcip.annotations.ThreadSafe
    -dontwarn com.google.crypto.tink.subtle.XChaCha20Poly1305
    

    Perhaps with a later update of R8 it will get smarter about this, but I can’t see any way to fix this directly. This seems like typical workaround for dependencies that’s just part of life using gradle and proguard 😅

    Thanks again for your help! Perhaps adding the above to the README could be helpful for future users of the library

  9. Matt King reporter

    Cheers Vladimir!

    Just a small thing I noticed, one of the rules says -json-dontwarn - is that intentional? I don’t know if that’s valid…I can’t seem to find any reference for it.

  10. Log in to comment