如何签名已编译的Apk

170

我使用apktool解码了一个APK(因为原始源代码已丢失),以便可以修复与布局xml文件相关的一些问题。然后,我使用apktool重新构建了它,并尝试在我的设备上安装它(使用adb:adb install appname.apk),但遇到如下错误:

[INSTALL_PARSE_FAILED_NO_CERTIFICATES]

原始的apk被一个密钥库(在Eclipse IDE上)签名,而这个apk没有签名,请问如何使用其原始的密钥库文件在Eclipse之外正确地签名它?


1
是的,证书的整个目的就是阻止人们这样做...如果你没有原始证书,你将不得不重新生成一个。 - edthethird
就是这样,我有原始证书,但解码/重建apk时将其删除了。 - svarog
1
注意:所有使用jarsigner的答案都已过时。最近的Android版本(AFAIR Android 10+)不接受由jarsigner签名的APK。您需要使用来自Android SDK的apksigner - Robert
6个回答

382

使用以下方法创建密钥:

keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000

然后使用以下方式对apk进行签名:

jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore my_application.apk alias_name

点击此处查看更多信息


12
这应该是答案,27个点赞对比原回答的3个,加油! - Kyle
2
如果您这样做并尝试安装APK,则可能会遇到INSTALL_FAILED_DUPLICATE_PERMISSION错误。当原始APK无法被覆盖(例如系统或内置应用程序)时,就会发生这种情况。 - Couitchy
21
如果您不想麻烦地创建密钥,可以使用调试密钥,并执行以下操作:jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ~/.android/debug.keystore app.apk androiddebugkey -storepass android。 - Pellet
4
jarsignerapksigner有什么区别?其中一个需要签名后再进行zipalign,另一个需要先进行zipalign,然后再签名。 - Maria Ines Parnisari
调试密钥自SDK安装后只有1年有效期,因此不建议在发布中使用它。 - snuk182
显示剩余8条评论

132

自动化流程:

使用此工具(使用谷歌的新apksigner):

https://github.com/patrickfav/uber-apk-signer

免责声明:我是开发者 :)

手动流程:

步骤1:生成密钥库(仅需一次)

您需要生成一个密钥库,并使用它来签名您的未签名 apk。 使用JDK提供的keytool %JAVA_HOME%/bin/中找到

keytool -genkey -v -keystore my.keystore -keyalg RSA -keysize 2048 -validity 10000 -alias app

第2或第4步:Zipalign zipalign是Android SDK提供的工具,可以在例如%ANDROID_HOME%/sdk/build-tools/24.0.2/中找到。如果您想要将apk上传到Play商店,这是一个必需的优化步骤。
zipalign -p 4 my.apk my-aligned.apk

注意:使用旧的jarsigner时,需要在签名后进行zipalign操作。而使用新的apksigner方法时,需要在签名之前进行zipalign操作(很令人困惑,我知道)。因为apksigner保留了APK的对齐和压缩(与jarsigner不同),所以在apksigner之前进行zipalign操作是可行的。
您可以使用以下方法来验证对齐性:
zipalign -c 4 my-aligned.apk

步骤3:签名和验证

使用24.0.3及更新版本的构建工具

Android 7.0引入了APK签名方案v2,这是一种新的应用程序签名方案,提供更快的应用安装时间,并且对APK文件的未经授权的更改提供更多保护(请参阅此处此处以获取更多详细信息)。因此,Google实现了他们自己的apk签名工具apksigner(当然!) 脚本文件可以在%ANDROID_HOME%/sdk/build-tools/24.0.3/中找到(.jar文件位于/lib子文件夹中)。使用方法如下:

apksigner sign --ks-key-alias alias_name --ks my.keystore my-app.apk

可以通过验证。
apksigner verify my-app.apk

官方文档可以在这里找到。

使用 build-tools 24.0.2 及更早版本

使用 jarsigner,就像 keytool 一样,它与 JDK 分发版一起提供,可以在 %JAVA_HOME%/bin/ 中找到,并按照以下方式使用:

jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my.keystore my-app.apk my_alias_name

并可通过验证

jarsigner -verify -verbose my_application.apk

7
感谢Uber APK签名工具!非常好用的工具! - cantoni
2
对于构建工具 24.0.3,调用 zipalign 的正确方式是: zipalign -p 4 my.apk my-aligned.apk - kinORnirvana
感谢您的描述!我首先尝试了uber-apk-signer,但失败了,可能是因为我在系统上安装了openJDK而不是Oracle的“官方”Java。所以我尝试了手动方式,但仍然失败(仍然出现相同的错误[INSTALL_PARSE_FAILED_NO_CERTIFICATES])。使用uber-apk-signer进行验证给了我一些进一步的见解signature VERIFY FAILED[...] `ERROR: JAR signer CERT.RSA: JAR signature META-INF/CERT.RSA使用摘要算法2.16.840.1.101.3.4.2.1和签名算法1.2.840.113549.1.1.1,这在API级别[[15, 17]]上不受支持。是的,Android 4.2.2,SHA256不在那里?有什么想法吗? - antiplex
@antiplex请在Github上报告问题而不是Stack Overflow。 - Patrick
@for3st,您的意思是我的问题可能不是由于我对apk签名的知识有限,而是由于Uber-apk-signer的某种不兼容性引起的吗?但即使如此,手动方式也失败了,这似乎与您的工具无关... - antiplex
显示剩余5条评论

18

最快的方式是使用调试密钥库进行签名:

jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ~/.android/debug.keystore app.apk androiddebugkey -storepass android

或在Windows上:

jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore %USERPROFILE%/.android/debug.keystore test.apk androiddebugkey -storepass android

jarsigner已被弃用,不应再使用。由jarsigner签名的APK将无法在最新的Android版本上运行。 - Robert

7

1
链接已经失效。 - jayatubi

4

对于那些不想为每个项目创建批处理文件,或者不想记住与keytools和jarsigner程序相关的所有命令,只想在一个过程中完成操作的人,请使用此程序:

http://lukealderton.com/projects/programs/android-apk-signer-aligner.aspx

我建立了这个程序,因为我厌倦了每次都要输入所有文件位置的冗长过程。
这个程序可以保存您的配置,下次启动它时,您只需要点击生成,它就会为您处理。就是这样。
无需安装,完全便携,并将其配置保存在同一文件夹中的CSV中。

对我无效。未将证书添加到APK中。似乎什么也没做。甚至不要求别名密码。 - Velda

2

1
很可能是因为这是一个旧帖子,你可以看一下这个链接: https://shatter-box.com/knowledgebase/android-apk-signing-tool-apk-signer/ - shereifhawary
两个链接现已过时,请勿使用。 - Epic Speedy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接