这几天遇到一件怪事,使用加固工具后,打包出来的APK无法在Android 4.2版本的手机上安装,不使用加固打出来的安装包却可以安装。于是找加固厂商询问原因,加固厂商拿了不能安装的文件后,又发了一个安装包让我们测试一下,结果可以了。询问原因,说是我们给的安装包没有签名,加上签名信息就好了。于是用 keytool
工具看了下原安装文件的签名信息,发现都有。把执行命令包含有签名信息的截图发过去了之后,加固厂商问了使用的签名工具,然后说是用 jarsigner
工具的问题。于是一查,还真是。
原来默认打包使用的是 gradlew assembleRelease
命令,使用这个命令默认使用的是Android SDK中的 apksigner
命令读取gradle文件中的签名信息进行签名。这就解释了为什么没有加固的安装包可以正常安装。
因为加固后,需要重新签名,这时自动打包在jenkins上使用的是 jarsigner
命令进行签名。而这个工具是由jdk提供的,而且不同的jdk版本的算法不一致。在jdk7版本开始使用SHA256,而4.2系统版本只支持SHA1,所以导致无法安装。
解决办法是执行 jarsigner
命令时,使用参数,命令如下所示:
jarsigner -keystore debug.keystore -digestalg SHA1 -sigalg SHA1widthRSA -signedjar test_signed.apk test_unsigned.apk
即要加上 -digestalg SHA1 -sigalg SHA1widthRSA
参数即可。
但是上述方法不推荐,因为在Android 7.0版本以上会使用V2签名,v1签名会有Janus安全漏洞,所以签名apk文件时还是得使用 apkSigner
比较好。
命令如下所示:
java -jar apksigner.jar sign --v1-signing-enabled true --v2-signing-enabled true --ks D:/test.jks --ks-pass pass:storePassword --ks-key-alias keyAlias --key-pass pass:keyPassword --in unsigned.apk --out signed.apk
apksigner.jar
文件是在Android SDK的build-tool目录中相应版本目录中的lib目录下。注意这两个参数 --v1-signing-enabled true --v2-signing-enabled true
是可选,如果不加这两个参数,其默认值为true,这样可以在android 7.0版本以上避免Janus安全漏洞。另外还要注意密钥之前要加上 pass:
前缀。
查看apk签名信息的命令如下所示:
java -jar apksigner.jar verify -v --print-certs 1.apk
查看签名文件中的签名信息的命令如下所示:
keytool -list -v -keystore D:/test.jks
输入密钥库口令后即可输出签名信息。