How to sign android app with platform keys using gradle?

13,009

Solution 1

for create a keystore from x509.pem and pk8 files, you can use this script platform_import_keystore which is similar to keytool-importkeypair, but given that keytool-importkeypair doesn't work if you don't have a keystore already existing, platform_import_keystore will do.

I hope it will help.

EDIT :

The script platform_import_keystore is using the default keytool command. You must ansure that the command keytool which is used in the script is from java 8. This influences the keystore format got by keytool.

Solution 2

Please try using the .keystore variant. There could be ways to fix the java keystore (.jks) format but it is likely to take more time.

1) Generate your .keystore file from your separate key files

$ openssl pkcs8 -inform DER -nocrypt -in \
  $ANDROID_ROOT/build/target/product/security/platform.pk8 -out platform.key
$ openssl pkcs12 -export -in \
  $ANDROID_ROOT/build/target/product/security/platform.x509.pem -inkey \
  platform.key -name platform -out platform.pem -password pass:password
$ keytool -importkeystore -destkeystore platform.keystore -deststorepass \
  password -srckeystore platform.pem -srcstoretype PKCS12 -srcstorepass 
  password

2) Test your new keystore:

$ jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore \
  platform.keystore -storepass password your-app.apk platform

3) Deploy keystore in your gradle build:

signingConfigs {
 debug {
    storeFile     file('debug.keystore')
    storePassword 'android'
    keyAlias      'androiddebugkey'
    keyPassword   'android'
 }
 release {
    storeFile     file('platform.keystore')
    storePassword 'password'
    keyAlias      'platform'
    keyPassword   'password'
 } 
}

The above build.gradle is also showing an example of using the android debug keystore as standard for debug builds.

Solution 3

After chat with deadfish and following his suggestions (thanks for help!) I've come up with following workaround in app/build.gradle (inside android {}):

applicationVariants.all { variant ->
    variant.assemble.doLast {
        exec {
            commandLine 'sh', '../mySigningScript.sh'
        }
    }
}

This will run my script everytime when assembleDebug or assembleRelease is finished. I will not accept my answer because it's not answering my question and it forces me to remove signingConfigs from gradle but at least it's a workaround which potentially could be used if no better solution is proposed.

Share:
13,009
LLL
Author by

LLL

Just a random programmer

Updated on June 05, 2022

Comments

  • LLL
    LLL almost 2 years

    I saw couple similar questions like:

    but I feel my problem is different.

    First of all I use:

    android:sharedUserId="android.uid.system"

    so I need to sign my app with platform key. I'm able to do that in this way:

    cd $ANDROID_ROOT/out/host/linux-x86/framework
    java -Djava.library.path=$ANDROID_ROOT/out/host/linux-x86/lib64 -jar signapk.jar $ANDROID_ROOT/build/target/product/security/platform.x509.pem $ANDROID_ROOT/build/target/product/security/platform.pk8 $APP_DIR/app/build/outputs/apk/debug/app-debug.apk $APP_DIR/MyApp-signed.apk
    

    However I want to do signing from gradle, so I have generated jks file in this way:

    ./keytool-importkeypair -k my_keystore.jks -p my_password -pk8 $ANDROID_ROOT/build/target/product/security/platform.pk8 -cert $ANDROID_ROOT/build/target/product/security/platform.x509.pem -alias platform
    

    and I've modified app/build.gradle to have:

     signingConfigs {
         release {
             storeFile file("my_keystore.jks")
             storePassword "my_password"
             keyAlias "platform"
             keyPassword "my_password"
         }
     }
    
     buildTypes {
         release {
             minifyEnabled false
             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    
             signingConfig signingConfigs.release
         }
     }
    

    I've checked that my_keystore.jks has platform alias with:

    keytool -list -v -keystore my_keystore.jks | grep Alias
    Alias name: platform
    

    but when I try to do:

    ./gradlew assembleRelease
    

    or:

    ./gradlew signingReport
    

    I get:

    Failed to read key platform from store "(...)/my_keystore.jks": Invalid keystore format

    Update: I've tried following dr_g tips and I'm able to sign app using Android Studio (Build -> Generate Signed APK), so I guess keystore is ok, but still I get the same error when using assembleRelease. I've also tried generating my own keystore as suggested by deadfish and indeed keystore generated by Android Studio is fine for gradle and assembleRelease works, but it's not platform key, so I can't use it unfortunately.

    Issue solved: It turned out that my problem was indeed different than the ones I've mentioned. It was related with keytool used for generating keys (not gradle), and it was because although my default java was 8, my default keytool was from java 10 … When I’ve switched to keytool from java 8 everything started to work fine.

  • LLL
    LLL almost 6 years
    I'm not sure if I understood you correctly, however when I've changed extension from .jks to .keystore the result was the same.
  • LLL
    LLL over 5 years
    Thanks for answer, I will try it next week and hopefully it will work
  • LLL
    LLL over 5 years
    I've did exactly as you wrote (and built app with ./gradlew assembleRelease) but I still get the same error. Which currently is: ~Failed to read key platform from store "(...)/app/platform.keystore": Invalid keystore format.~ This usually indicates wrong password, however I've copy-pasted both commands and app/build.gradle file, so my password is just password. I've also tested keystore file (point 2) and it works, however as in the question I'm looking for a way to make it work in gradle, so unfortunately my problem is still open.
  • LLL
    LLL over 5 years
    I've even created fresh template app and repeated all the steps but I get the same error. The interesting thing is that when I do Build -> Generate Signed APK from Android Studio and I choose platform.keystore manually then it works but still "./gradlew signingReport" and "./gradlew assembleRelease" both give me "Invalid keystore format" error ...
  • dr_g
    dr_g over 5 years
    Have you tested using the android debug key, and does this work without errors? If so I would compare the two signing configs. To avoid errors or typos try to open the Project Structure window and select your app module in the left hand pane, and then select the Signing tab. Verify all the entries are correct. It feels to me like the alias or the password has become mixed up. It is also worth cleaning the project completely using ./gradlew clean and ./gradlew cleanBuildCache and/or deleting the hidden .gradle folder.
  • LLL
    LLL over 5 years
    I've generated my own keystore using android studio and it works without a problem (so I guess my build.gradle is ok), which indicates problem with platform.keystore. However as I wrote previously - using platform.keystore from Android Studio works, so I think keystore is ok and there is something wrong with gradle. I've already compared signing configs with "keytool -list -v -keystore app/platform.keystore" and they are a bit different but in general they both look ok. One such difference is that platform.keystore has "Keystore type: PKCS12" while ASgenerated.keystore has "Keystore type: JKS"
  • LLL
    LLL over 5 years
    As to cleaning I've already tried that but it didn't help. As to typos in alias or password then if I would do such typo then I wouldn't be able to sign app from Android Studio, but I'm able to do that. I'm only not able to do that when executing ./gradlew assembleRelease
  • LLL
    LLL over 5 years
    Thanks for answer. I've tried using your script in following way: ./platform_import_keystore.sh -k testpass -p testpass -a platform but I get: keytool error: java.lang.UnsupportedOperationException: -keypasswd commands not supported if -storetype is PKCS12. When I don't provide -k parameter I get request to give password and when I provide testpass I get keytool error: java.io.IOException: keystore password was incorrect
  • LLL
    LLL over 5 years
    It's not my git but I'm using the same x509 and pk8 files as can be found here: github.com/tanzirul/a3e/blob/master/tools/platform.x509.pem github.com/tanzirul/a3e/blob/master/tools/platform.pk8 so you can check on your own if you want.
  • VelocityPulse
    VelocityPulse over 5 years
    It work perfectly on my computer and i get the keystore.jks.
  • VelocityPulse
    VelocityPulse over 5 years
    The password is required because i don't have the solution for make a keystore from 509.pem and pk8 without keystorepass and keypass. The both must have password, its the concept of the key and his keystore
  • VelocityPulse
    VelocityPulse over 5 years
    Here is my log with your platform.x509.pem and platform.pk8 file with your command line : pastebin.com/3SBMer7E
  • LLL
    LLL over 5 years
    Thanks for checking and sorry for confusion. The error I've pasted was actually a warning. So keystore.jks was generated (with md5sum f4b4f9b92f635625c81cc668af688542 app/keystore.jks). However I'm unable to use it due to the same "Invalid keystore format" error I had. This is what I have in my app/build.gradle: pastebin.com/3Gxmr2DV
  • VelocityPulse
    VelocityPulse over 5 years
    Please can you try to put the complete path in your gradle in your storeFile file ? I don't understand why the gradle say "invalid format" given that we get a jks, and that the signing work on my project
  • LLL
    LLL over 5 years
    The path is ok, if I change it to something else I get something like: 'xxxkeystore.jks' not found for signing config 'release'. But anyway, I've checked full path and the error is the same :(
  • LLL
    LLL over 5 years
    Thanks for checking though. Maybe it's gradle issue? I'm using Gradle 4.5 Revision: 77d0ec90636f43669dc794ca17ef80dd65457bec (checked with: ./gradlew --version). Or maybe it works for you on Windows but doesn't work for me on Linux. Anyway I've created ticket on gradle forum some time ago, but no answers yet: discuss.gradle.org/t/invalid-keystore-format-only-in-gradle/‌​…
  • VelocityPulse
    VelocityPulse over 5 years
    The os difference is a possibility. Can you ensure that your key in your keystore is all correct by executing this commande ? keytool -J-Duser.language=en -list -v -keystore keystore.jks -storepass testpass Here is mine : pastebin.com/CQfKr68v If there is no difference, its probably a problem in your gradle configuration.
  • LLL
    LLL over 5 years
    Thanks, of course I'll check it (but tomorrow). As to gradle configuration I don't have any magic, at least the one I would be aware of. I've even tried creating dummy project from scratch via Android Studio and I had the same problem. Anyway I'll check if your keystore has the same md5sum and try the option which you've mentioned.
  • LLL
    LLL over 5 years
    Mine is here: pastebin.com/868jNi6X The main difference I see is that you have keystore type JKS while I have PKCS12 but sha1 is the same, so maybe it's only the difference in print output generated by keytool. I've also tried again creating dummy project from scratch but the error is the same, so it's not something related to my code or configuration unfortunately.
  • VelocityPulse
    VelocityPulse over 5 years
  • LLL
    LLL over 4 years
    He wrote couple comments under my question and then started chat with me during which we came to solution, so that's why I refer him ;)