[RK3399][Android7.1] 调试笔记 --- app安装失败提示证书有问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kris_fei/article/details/84766460

Platform: RK3399
OS: Android 7.1
Kernel: v4.4.83

现象:

在rk3288上预置的apk放到rk3399平台上确不能使用了,出现error log如下:

Failed to parse /data/app/Ben3.0.AudioService: Failed to collect certificates from /data/app/Ben3.0.AudioService/Ben3.0.AudioService.apk

app安装逻辑:

app是被预置在/system/etc/目录下,恢复出厂设置时会被copy到/data/app目录下,
按照系统执行逻辑,在下一次重启的时候,如果签名正确,那么就会被正常地安装到/data/app下。


分析调试过程:

  1. 由于我是预置了多个app,奇怪的是有些是能正常安装的,但是都是用同一个签名文件打包的,很诡异。
  2. 查看验证签名的源代码, 出现异常是在new StrictJarFile()部分。
private static void collectCertificates(Package pkg, File apkFile, int parseFlags)
	......
	boolean verified = false;
	try {
		Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV2");
		allSignersCerts = ApkSignatureSchemeV2Verifier.verify(apkPath);
		signatures = convertToSignatures(allSignersCerts);
		// APK verified using APK Signature Scheme v2.
		verified = true;
	} catch (ApkSignatureSchemeV2Verifier.SignatureNotFoundException e) {
                // No APK Signature Scheme v2 signature found
    }
	......
	jarFile = new StrictJarFile(
		apkPath,
		!verified, // whether to verify JAR signature
		signatureSchemeRollbackProtectionsEnforced);
	......
}
  1. 代码跟进去:
    StrictJarFile -> verifier.readCertificates -> verifyCertificate
    然后在if(signatureSchemeRollbackProtectionsEnforced)部分exception了。
    这是android在7.0之后对签名的回滚保护机制,不深究。
  2. 查看正常安装的apk,发现根本没跑进verifier.readCertificates(),因为在new StrictJarFile()的参数中,
    正常安装的app是true的!也就是说,不能安装的app是因为V2签名验证的时候发生SignatureNotFoundException了!
    这样后面的verified=true跑不到导致结果是false了!
  3. 直接将app放到/data/app/目录下重启,意外的是能安装成功了!也就是说问题可能出在预置apk后的编译阶段了。
  4. 查看原生和生成的app,发现不能安装的app会比正常安装的生成出来大很多!但是编译方法是rk3288一致,并没有改动。
    附Android.mk
LOCAL_PATH := $(call my-dir)

$(foreach a, $(wildcard $(LOCAL_PATH)/*.apk), \
	$(eval include $(CLEAR_VARS)) \
	$(eval LOCAL_MODULE := $(a:$(LOCAL_PATH)/%.apk=%)) \
	$(eval LOCAL_MODULE_CLASS := APPS) \
	$(eval LOCAL_BUILT_MODULE_STEM := package.apk) \
	$(eval LOCAL_CERTIFICATE := PRESIGNED) \
	$(eval LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/benebot) \
	$(eval LOCAL_MODULE_TAGS := optional) \
	$(eval LOCAL_SRC_FILES := $(LOCAL_MODULE).apk) \
	$(eval include $(BUILD_PREBUILT)) \
)
  1. 再做观察比较,发现安装异常的app都是调用了JNI的,也就是加载了so。 而默认使用的so是基于armv7编译的,rk3399是基于armv8架构。
  2. 把so移除做测试之后果然安装成功。因此是JNI对应的so不匹配,导致系统编译的时候重新做了解析,最终签名对应的app内容有了变化而不能安装成功。

原因:

google为了安全考虑,在安卓7.0之后的系统结合Signature Scheme v2 签名方法进行安装包校验,凡是经过修改的安装包,都无法安装(在7.0之前则没有这个检验,可以进行安)


解决方法:

  1. 设置LOCAL_CERTIFICATE := platform, 使app从新签名打包,不过这样有可能导致后面app推送替换会有签名问题。
  2. Android Studio中添加配置: v2SigningEnabled false

参考:

android apk安装包修改了之后在安卓7.0系统上无法安装的解决办法
Android应用程序签名验证过程分析
Android签名机制之—签名过程详解
3个知识点让你了解Android签名机制

猜你喜欢

转载自blog.csdn.net/kris_fei/article/details/84766460