如何使用 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 StudioMenu>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 应用程序?的主要内容,如果未能解决你的问题,请参考以下文章