标题: 对apk签名时的坑 https://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 install -r -s com.anything.something_20160824-release.apk $ adb -s install -r -s com.anything.something_20160824-release-2.apk $ adb -s uninstall com.anything.something 这里碰上个跟本文标题无关的困惑,不知为何,对于模拟器-s会失败,我分配了1GB 的SD卡,安装时仍然提示: INSTALL_FAILED_CONTAINER_ERROR