[FAQ19857]采用Signature Scheme v2签名方式的APK预置进系统失败

[DESCRIPTION]
Google在N上引入了一项新的应用签名方案Signature Scheme v2,它能提供更快的应用安装时间和更多针对APK文件更改的保护
在N上预置APK时,如果APK是采用的Signature Scheme v2签名,采用原有的预置应用方式预置APK会失败:

Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: Failed to collect certificates fr
om /data/app/vmdl1483607312.tmp/base.apk: META-INF/CERT.SF indicates /data/app/v
mdl1483607312.tmp/base.apk is signed using APK Signature Scheme v2, but no such
signature was found. Signature stripped?]
 
 
[SOLUTION]
经过BUILD_PREBUILT后的apk与原apk是有差异的,因为v2是对apk整体签名,所以这个差异导致签名失效;
1、放入到工程用android.mk编译之后的APK是有区别的,android编译系统会用zipalign对APK进行字节对齐等操作
2、APK Signature Scheme v2这个是Google在N上新引入的签名方式:v2 签名将验证归档中每个文件的已压缩文件内容,如有任何自定义任务篡改 APK 文件或对其进行后处理(无论以任何方式),那么v2 签名会有作废的风险

在预置APK build进系统时候不让其走编译流程,在其他模块的android.mk加入下面的cp脚本:
$(shell cp $(LOCAL_PATH)/***/*.apk $(TARGET_OUT)/vendor/operator/app)
 
APK能通过PMS扫描安装成功,可能还会报so找不到的问题,可以参考:
ID: FAQ19894
[FAQ19894]N上预置APK失败提示找不到so文件
[DESCRIPTION]
预置APK到系统之后打开APK会提示:
01-01 12:00:39.537 5326 5326 E AndroidRuntime: Process: com.skype.raider, PID: 5326
01-01 12:00:39.537 5326 5326 E AndroidRuntime: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList<a id="0::zip file " vendor="" operator="" app="" skype="" skype.apk"],nativelibrarydirectories="[/data/app-lib/Skype,/vendor/operator/app/Skype/S|lib"" class="ms-missinglink" href="https://onlinesso.mediatek.com/FAQ/Skype/S" target="_blank" style="box-sizing: border-box; color: rgb(102, 51, 153); text-decoration-line: none; background-color: transparent; border-bottom: 1px dashed rgb(0, 114, 198);">lib] couldn't find "libSkypeAndroid.so"
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:972)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at java.lang.System.loadLibrary(System.java:1530)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.skype.android.util.CrashAndAnrHandler.<clinit>(SourceFile:19)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.skype.android.util.CrashAndAnrHandler.saveHandlers(Native Method)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.skype.android.skylib.SkyLibInitializer.a(SourceFile:115)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.skype.android.SkypeModule.a(SourceFile:126)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.skype.android.SkypeModule_SkyLibFactory.get(SourceFile:37)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.skype.android.SkypeModule_SkyLibFactory.get(SourceFile:11)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at dagger.internal.d.get(SourceFile:47)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.skype.android.app.BackgroundMode_Factory.get(SourceFile:72)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.skype.android.app.BackgroundMode_Factory.get(SourceFile:16)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at dagger.internal.d.get(SourceFile:47)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.skype.android.wakeup.DreamKeeper_Factory.get(SourceFile:48)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.skype.android.wakeup.DreamKeeper_Factory.get(SourceFile:12)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at dagger.internal.d.get(SourceFile:47)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.skype.android.wakeup.ForegroundObserver_Factory.get(SourceFile:34)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.skype.android.wakeup.ForegroundObserver_Factory.get(SourceFile:8)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at dagger.internal.d.get(SourceFile:47)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.skype.android.SkypeApplication_MembersInjector.injectMembers(SourceFile:160)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.skype.android.SkypeApplication_MembersInjector.injectMembers(SourceFile:24)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.skype.android.DaggerSkypeApplicationComponent.inject(SourceFile:2266)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.skype.android.SkypeApplication.onCreate(SourceFile:152)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1027)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5503)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at android.app.ActivityThread.-wrap2(ActivityThread.java)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1595)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:110)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at android.os.Looper.loop(Looper.java:203)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6251)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
01-01 12:00:39.537 5326 5326 E AndroidRuntime: FATAL EXCEPTION: main
 
 
[SOLUTION]
这是因为Google在N上对selinux有更严格的限制,APK的so文件被selinux挡住了:
01-01 12:00:39.520000  5326  5326 W om.skype.raider: type=1400 audit(0.0:64): avc: denied { read } for name="libSkypeAndroid.so" dev="mmcblk0p22" ino=770074 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:system_data_file:s0 tclass=file permissive=0
 
参考如下的solution:
Add the policy to alps/device/mediatek/common|[platfrom]/sepolicy/basic|bsp|full/xxx.te
#====================== untrusted_app.te ======================
allow untrusted_app system_data_file:file r_file_perms;



怎么知道APK是不是采用Signature Scheme v2签名?
可参考:http://blog.bihe0832.com/android-v2-signature.html

[FAQ20235]如何知道APK是不是采用Signature Scheme v2签名?

[DESCRIPTION]
 
     Google在N上引入了一项新的应用签名方案Signature Scheme v2,如何知道一个apk是否使用的是Signature Scheme v2
   签名。
 
[SOLUTION]
 
    使用apksigner.jar工具的verify命令。这个工具位于SDK目录的build-tools目录下。打开cmd,把目录切到SDK\build-tools\版本号\lib下。
    注:v2签名方式时在Android7.0后才推出的,所以只有 版本>25的SDK\build-tools\中才能找到apksigner.jar
    
    
    具体可以参考:https://developer.android.com/studio/command-line/apksigner.html#usage。



Android的APK Signature Scheme v2签名及一款基于Java环境的校验工具介绍

背景

APK Signature Scheme v2官方介绍

Android 7.0 引入一项新的应用签名方案 APK Signature Scheme v2,它能提供更快的应用安装时间和更多针对未授权 APK 文件更改的保护。在默认情况下,Android Studio 2.2 和 Android Plugin for Gradle 2.2 会使用 APK Signature Scheme v2 和传统签名方案来签署您的应用。

如果您使用 APK Signature Scheme v2 签署您的应用,并对应用进行了进一步更改,则应用的签名将无效。出于这个原因,请在使用 APK Signature Scheme v2 签署您的应用之前、而非之后使用 zipalign 等工具。

官方关于v2的详细介绍:https://source.android.com/security/apksigning/v2.html

渠道或者开发者关于渠道包的解决方案

目前主流的渠道号方案主要有以下几种:

  1. 修改后重新打包或签名的,例如在AndroidMainfest里面添加mata-data等
  2. 修改后不需要重新签名,主要有两种:

    • 直接把apk包看成一个zip包,然后在zip包的注释段添加对应的渠道信息
    • 直接把apk包看成一个zip包,然后利用相关命令在META-INF内注入${channel}.txt 文件

其中下面两种不需要重新签名的方法,被各主要渠道广泛使用。

渠道包与V2签名的冲突

然而,为了提高Android系统的安全性,Google从Android N增强了签名模式,该模式在原有的签名模式上,增加校验APK的SHA256哈希值;这种新引入的签名机制,会对整个文件的每个字节都会做校验,包括 comment 区域。如果签名后对APK作了任何修改,例如上面提到的修改注释段或者注入文件,在Android 7.0以上的机型安装时都会校验失败,提示没有签名无法安装。

解决方案

为了解决使用V2引起的问题,官方提供了不启用V2签名的方法,但是随着Android越来越完善,这种方案最终肯定是要全面使用的。目前已经有团队找到了基于V2签名的新的渠道号方案,由于种种原因,暂时不详细论述怎么实现。这里仅提供其余的解决方案:

怎么禁用V2签名

对于怎么禁用V2签名,官方提供了对应的方法,下文内容为禁用方法

虽然我们建议您对您的应用采用 APK Signature Scheme v2,但这项新方案并非强制性的。如果您的应用在使用 APK Signature Scheme v2 时不能正确开发,您可以停用这项新方案。禁用过程会导致 Android Studio 2.2 和 Android Plugin for Gradle 2.2 仅使用传统签名方案来签署您的应用。要仅用传统方案签署,打开模块级 build.gradle 文件,然后将行 v2SigningEnabled false 添加到您的版本签名配置中:

  android {
    ...
    defaultConfig { ... }
    signingConfigs {
      release {
        storeFile file("myreleasekey.keystore")
        storePassword "password"
        keyAlias "MyReleaseKey"
        keyPassword "password"
        v2SigningEnabled false
      }
    }
  }

官方说明对应地址:https://developer.android.google.cn/about/versions/nougat/android-7.0.html

怎么检查一个apk是否使用了V2签名以及V2校验是否通过

对于渠道SDK的开发者或者渠道来说,如果开发者上传的应用V2签名校验不能通过的话,那将是非常严重的问题,这样的安装包在Android 7.0以上版本的机器上是完全无法安装的。目前官方提供了校验一个apk签名校验是否通过的工具。

除了官方没有提供的工具。通过阅读源码发现在ApkSignatureSchemeV2Verifier.java里面也有对应的逻辑实现,目前个人已经把对应代码迁移出来制作了独立的工具提供使用。

工具下载
使用事例
  • 查看帮助

        java -jar CheckAndroidV2Signature.jar
    
      usage: java -jar ./CheckAndroidV2Signature.jar [--version] [--help] [filePath]
    	
      such as:
    	
           java -jar ./CheckAndroidV2Signature.jar --version
           java -jar ./CheckAndroidV2Signature.jar --help
           java -jar ./CheckAndroidV2Signature.jar ./test.apk
    	
      after check,the result will be a string json such as:
    	
           {"ret":0,"msg":"ok","isV2":true,"isV2OK":true}
    	
           ret: result code for check
    	
               0 : command exec succ
               -1 : file not found
               -2 : file not an Android APK file
               -3 : check File signature error ,retry again
    	
           msg: result msg for check
           isV2: whether the file is use Android-V2 signature or not
           isV2OK: whether the file's Android-V2 signature is ok or not
  • 查看版本

        java -jar ./CheckAndroidV2Signature.jar --version
      com.tencent.ysdk.CheckAndroidV2Signature version 1.0.1 (CheckAndroidV2Signature - 2)
      homepage : https://github.com/bihe0832/AndroidGetAPKInfo
      blog : http://blog.bihe0832.com
      github : https://github.com/bihe0832		
  • 查看应用信息

        java -jar ./CheckAndroidV2Signature.jar ./YSDK_Android_1.3.1_629-debug-ysdktest-inner.apk
      {"ret":0,"msg":"ok","isV2":false,"isV2OK":false}
源码地址:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值