如何使用 gradle 使用平台密钥签署 android 应用程序?

Posted

技术标签:

【中文标题】如何使用 gradle 使用平台密钥签署 android 应用程序?【英文标题】:How to sign android app with platform keys using gradle? 【发布时间】:2019-01-14 08:47:05 【问题描述】:

我看到了几个类似的问题,例如:

android: After building platform source, how to sign arbitrary APK with platform key? How to create a release signed apk file using Gradle? APK signing error : Failed to read key from keystore

但我觉得我的问题不一样。

首先我使用:

android:sharedUserId="android.uid.system"

所以我需要使用平台密钥签署我的应用程序。我可以通过这种方式做到这一点

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

但是我想从 gradle 进行签名,所以我以this 方式生成了 jks 文件:

./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

我已经修改了 app/build.gradle:

 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
     
 

我检查了 my_keystore.jks 的平台别名:

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

但是当我尝试这样做时:

./gradlew assembleRelease

或:

./gradlew signingReport

我明白了:

无法从存储“(...)/my_keystore.jks”读取密钥平台:密钥库格式无效

更新: 我已经尝试遵循 dr_g 提示,并且我能够使用 Android Studio (Build -> Generate Signed APK) 对应用程序进行签名,所以我猜 keystore 没问题,但在使用时我仍然遇到同样的错误组装发布。 我还尝试按照 deadfish 的建议生成自己的密钥库,并且确实由 Android Studio 生成的密钥库适用于 gradle 和 assembleRelease 工作,但它不是平台密钥,所以很遗憾我不能使用它。

问题已解决: 事实证明,我的问题确实与我提到的问题不同。它与用于生成密钥(不是 gradle)的 keytool 有关,这是因为虽然我的默认 java 是 8,但我的默认 keytool 来自 java 10……当我从 java 8 切换到 keytool 时,一切都开始正常工作了。

【问题讨论】:

您是否尝试在 Android Studio Menu>Build>Generate APK>[APK]>Create New... 中生成发布密钥?那么你的 gradle conf 应该可以工作了。 不,因为我需要平台密钥,而不仅仅是其他一些密钥。除了正如我在其中一个 cmets 中所写的那样,我能够从终端签署应用程序(使用 signapk)并且我能够从 Android Studio 签署它(所以我猜密钥库是好的),我只是不能直接使用 gradle 签名。我会更新问题以使其更清楚。 好的,但是当您以我的方式生成 apk 时,您稍后可以在终端 gradlew assembleRelease 中调用,或者只需单击 gradle 窗口 assembleRelease。通过读取您已定义的签名属性,Gradle 将能够使用发布密钥登录应用程序。 你有时间在聊天中谈论它吗? 我会尝试你的建议,我有时间在聊天中交谈,虽然我以前没有使用过,所以如果可以的话请启动它:) 【参考方案1】:

请尝试使用 .keystore 变体。可能有一些方法可以修复 java 密钥库 (.jks) 格式,但可能需要更多时间。

1) 从单独的密钥文件生成 .keystore 文件

$ 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) 测试您的新密钥库:

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

3) 在您的 gradle 构建中部署密钥库:

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

上面的 build.gradle 还展示了一个使用 android 调试密钥库作为调试构建标准的示例。

【讨论】:

谢谢你的回答,我下周试试,希望能成功 我已经完全按照你写的方式做了(并使用 ./gradlew assembleRelease 构建了应用程序),但我仍然遇到同样的错误。目前是: ~Failed to read key platform from store "(...)/app/platform.keystore": Invalid keystore format.~ 这通常表示密码错误,但是我已经复制粘贴了命令和 app/build .gradle 文件,所以我的密码就是密码。我还测试了密钥库文件(第 2 点)并且它可以工作,但是在问题中我正在寻找一种让它在 gradle 中工作的方法,所以不幸的是我的问题仍然存在。 我什至创建了新的模板应用程序并重复了所有步骤,但我得到了同样的错误。有趣的是,当我从 Android Studio 执行 Build -> Generate Signed APK 并手动选择 platform.keystore 时,它​​仍然可以工作,但仍然“./gradlew signingReport”和“./gradlew assembleRelease”都给了我“无效的密钥库格式”错误... 您是否使用 android 调试密钥进行了测试,是否可以正常工作?如果是这样,我会比较两个签名配置。为避免错误或拼写错误,请尝试打开“项目结构”窗口并在左侧窗格中选择您的应用模块,然后选择“签名”选项卡。验证所有条目是否正确。我觉得别名或密码已经混淆了。使用 ./gradlew clean 和 ./gradlew cleanBuildCache 彻底清理项目和/或删除隐藏的 .gradle 文件夹也是值得的。 我已经使用 android studio 生成了自己的密钥库,它可以正常工作(所以我猜我的 build.gradle 没问题),这表明 platform.keystore 有问题。然而,正如我之前写的那样——使用 Android Studio 中的 platform.keystore 可以工作,所以我认为 keystore 没问题,而且 gradle 有问题。我已经将签名配置与“keytool -list -v -keystore app/platform.keystore”进行了比较,它们有点不同,但总的来说它们看起来都不错。其中一个区别是 platform.keystore 具有“Keystore 类型:PKCS12”,而 ASgenerated.keystore 具有“Keystore 类型:JKS”【参考方案2】:

对于从 x509.pem 和 pk8 文件创建密钥库,您可以使用此脚本 platform_import_keystore,它类似于 keytool-importkeypair,但如果您使用 keytool-importkeypair 将不起作用没有现有的密钥库,platform_import_keystore 可以。

我希望它会有所帮助。

编辑:

脚本platform_import_keystore 使用默认的keytool 命令。您必须确保脚本中使用的命令keytool 来自java 8。这会影响keytool 获得的密钥库格式。

【讨论】:

感谢您的回答。我尝试通过以下方式使用您的脚本:./platform_import_keystore.sh -k testpass -p testpass -a 平台但我得到:keytool 错误:java.lang.UnsupportedOperationException:如果-storetype 是 PKCS12,则不支持-keypasswd 命令。当我不提供 -k 参数时,我收到提供密码的请求,当我提供 testpass 时,我收到 keytool 错误:java.io.IOException:keystore 密码不正确 这不是我的 git,但我使用的是相同的 x509 和 pk8 文件,可以在此处找到:github.com/tanzirul/a3e/blob/master/tools/platform.x509.pemgithub.com/tanzirul/a3e/blob/master/tools/platform.pk8,因此您可以根据需要自行检查。 它在我的电脑上完美运行,我得到了 keystore.jks。 密码是必需的,因为我没有解决方案从 509.pem 和 pk8 制作没有 keystorepass 和 keypass 的密钥库。两者都必须有密码,它的密钥和他的密钥库的概念 这是我的日志与您的 platform.x509.pem 和 platform.pk8 文件与您的命令行:pastebin.com/3SBMer7E【参考方案3】:

在与deadfish 聊天并遵循他的建议(感谢您的帮助!)后,我在 app/build.gradle(在 android 内)中提出了以下解决方法:

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

这将在每次 assembleDebug 或 assembleRelease 完成时运行我的脚本。我不会接受我的答案,因为它没有回答我的问题,它迫使我从 gradle 中删除signingConfigs,但至少这是一种解决方法,如果没有提出更好的解决方案,可能会使用它。

【讨论】:

他在我的问题下写了几个 cmets 然后开始和我聊天,在此期间我们找到了解决方案,所以这就是我推荐他的原因;)【参考方案4】:

使用 .keystore 文件而不是 .jks 当你生成你的应用程序时,Android Studio 会注意到你创建了一个 keyStore,试试这个 key。

【讨论】:

我不确定我是否理解正确,但是当我将扩展名从 .jks 更改为 .keystore 时,结果是一样的。

以上是关于如何使用 gradle 使用平台密钥签署 android 应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

未找到用于签署配置“发布”的密钥库。-- 反应原生

如何使用元掩码密钥签署超级账本锯齿交易?

如何使用 Google 签名密钥签署 apk 以上传到其他应用商店

sh 如何使用GPG密钥签署自定义RPM包

如何找出用于签署应用程序的密钥库?

如何在没有 android studio 的情况下签署 android apk