Skip to content

Latest commit

 

History

History
100 lines (54 loc) · 3.83 KB

201608250928.txt.md

File metadata and controls

100 lines (54 loc) · 3.83 KB

对apk签名时的坑

http://scz.617.cn/android/201608250928.txt

对apk签名是Android开发入门时就会碰上的问题,我从个人经历谈谈,不做全覆盖式 总结,只谈某些上下文里的坑。

我用Android Studio 2.1.2开发了一个apk,在此过程中,debug版的签名完全不用操心,我没深究在哪个环节由谁替我签了,我只知道debug版直接去模拟器上安装运行成功,那肯定是签过名了。

用AS生成release版时,用keytool生成JKS格式的keystore:

$ keytool -genkeypair -keystore ApkKeystore -alias Apk -keyalg RSA -validity 36500

签名过程是AS完成的,没有显式使用其他命令行工具。

用Apktool修改apk,重新编译打包得到:

com.anything.something_20160824-release-unsigned.apk

然后涉及重新签名,此时我想继续使用前述keystore中的数据,有两种方案。


1) keytool/jarsigner

keytool、jarsigner都是JDK中的工具,用AS的话,JDK肯定是安装了的。

$ jarsigner -digestalg SHA1 -sigalg MD5withRSA -keystore ApkKeystore -signedjar com.anything.something_20160824-release-unaligned.apk com.anything.something_20160824-release-unsigned.apk Apk

JDK 1.7之后"-signedjar"时,必须指定"-digestalg SHA1 -sigalg MD5withRSA"。老版JDK默认使用这两种算法,新版不是。

最初我不知道有这个坑,没有指定"-digestalg SHA1 -sigalg MD5withRSA",结果安装时提示:

INSTALL_PARSE_FAILED_NO_CERTIFICATES

但"jarsigner -verify"表明已签名。深究后就是现在看到的这样操作。

$ jarsigner -verify com.anything.something_20160824-release-unaligned.apk

jar 已验证。

优化:

$ zipalign -v 4 com.anything.something_20160824-release-unaligned.apk com.anything.something_20160824-release.apk

zipalign是Android SDK中的工具。


2) signapk.jar

这个比较流行,但这玩意不是Android SDK中的工具,也不是AS自带的,得从Android 源码中获取,比如:

./Android/4.2.1_r1.2/build/tools/signapk/SignApk.java ./Android/4.2.1_r1.2/out/4.2.1_r1.2/host/linux-x86/framework/signapk.jar

前面说过,我想继续使用keystore中的数据,而很多文章演示的是openssl直接生成证书文件、私钥文件。这中间的关键变成,如何从keystore中导出为signapk.jar所认格式的证书文件、私钥文件。

从JKS转换成PKCS#12格式:

$ keytool -importkeystore -srckeystore ApkKeystore -srcalias Apk -destkeystore Apk.p12 -srcstoretype JKS -deststoretype PKCS12

导出证书:

$ openssl pkcs12 -in Apk.p12 -out Apk.crt -nokeys

导出私钥:

$ openssl pkcs12 -in Apk.p12 -out Apk.pem -nodes -nocerts

将私钥转成PKCS#8格式:

$ openssl pkcs8 -topk8 -inform PEM -outform DER -in Apk.pem -out Apk.pk8 -nocrypt

对apk签名:

$ java -jar signapk.jar Apk.crt Apk.pk8 com.anything.something_20160824-release-unsigned.apk com.anything.something_20160824-release-unaligned-2.apk

优化:

$ zipalign -v 4 com.anything.something_20160824-release-unaligned-2.apk com.anything.something_20160824-release-2.apk

在我的上下文里,显然jarsigner是最佳选择。两种重签名方案分别得到:

com.anything.something_20160824-release.apk com.anything.something_20160824-release-2.apk

adb安装app测试:

$ adb -s <device> install -r -s com.anything.something_20160824-release.apk
$ adb -s <device> install -r -s com.anything.something_20160824-release-2.apk
$ adb -s <device> uninstall com.anything.something

这里碰上个跟本文标题无关的困惑,不知为何,对于模拟器-s会失败,我分配了1GB 的SD卡,安装时仍然提示:

INSTALL_FAILED_CONTAINER_ERROR