安卓安装包签名_笔记签名验证

安卓安装包签名_笔记签名验证我们知道,一款Android要发布的话,必须经过签名,Android目前支持的签名方式包括三种:v1方案:基于JAR签名。 v2方案:APK签名方案v2(在Android7.0中引入)。 v3方案:APK签名方案v3(在Android9中引入)。为了最大限度地提高兼容性,请按照v1、v2、v3的先后顺序采用所有方案对应用进行签名。与只通过v1方案签名…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

 我们知道,一款Android 要发布的话,必须经过签名,Android目前支持的签名方式包括三种:

为了最大限度地提高兼容性,请按照 v1、v2、v3 的先后顺序采用所有方案对应用进行签名。与只通过 v1 方案签名的应用相比,还通过 v2+ 方案签名的应用能够更快速地安装到 Android 7.0 及更高版本的设备上。更低版本的 Android 平台会忽略 v2+ 签名,这就需要应用包含 v1 签名。

v1签名方案

    在v1方案中,签名只保护apk中的元数据,也就是单个文件。apk其实就是一个zip文件,我们将打包签名好的apk文件,用解压缩文件解压,就可以看到一个名称为META-INF的文件夹里面。

安卓安装包签名_笔记签名验证

在META-INF文件夹中,存在3个文件,MANIFEST.MF , CERT.SF,CERT.RSA。这些就是v1版本的apk在安装时候,进行签名校验 很重要的文件。

MANIFEST.MF

  这个文件中保存着apk解压之后,所有文件(非文件夹)的信息,看下面的一段内容:

Manifest-Version: 1.0
Built-By: Generated-by-ADT
Created-By: Android Gradle 3.2.0

Name: AndroidManifest.xml
SHA1-Digest: g+psNXzyZSKU8DMfQr8FdR0KjXI=

Name: LICENSES
SHA1-Digest: +7g2kf8cIIZknpabOMYpXi8vrK8=

Name: META-INF/android.arch.core_runtime.version
SHA1-Digest: OxxKFJcpzAROGjnfMbNijNv1+JU=

Name: META-INF/android.arch.lifecycle_extensions.version
SHA1-Digest: BeF7ZGqBckDCBhhvlPj0xwl01dw=

Jetbrains全家桶1年46,售后保障稳定

在每个文件块中,其中 name就是解压之后,文件的名称(包含路径),而SHA1-Digets就是对文件的内容提取摘要之后 进行Base64之后生成的字符串内容。

CERT.SF

  先看一段CERT.SF的内容:

Signature-Version: 1.0
Created-By: 1.0 (Android)
SHA1-Digest-Manifest: 00yHda1FOBSkUAwjlTfipwkY+0k=
X-Android-APK-Signed: 2

Name: AndroidManifest.xml
SHA1-Digest: BNl/B2KAFMNJ1keEnqQ5+vkw8mY=

Name: LICENSES
SHA1-Digest: 9irOepAoIoOn8huusmI9KxjOT6c=

Name: META-INF/android.arch.core_runtime.version
SHA1-Digest: gfKdTxzy15iV0z7ZogHp7+qdek8=

SHA1-Digest-Manifest :是对整个MANIFEST.MF使用 SHA1算法之后,生成的Base64的编码的字符串。

Name:也是对应解压之后的文件的名称

SHA1-Digest:是对MANIFEST.MF中对应名称(Name)做SHA1之后生成再生成的Base64编码的字符串

CERT.RSA

这里会把之前生成的CERT.SF文件,用我们私钥计算出签名,然后将签名以及包含公钥信息的数字证书一同写入CERT.RSA中保存。

在mac电脑中,我们可以在终端中使用以下命令查看CERT.SF的内容:

openssl pkcs7 -inform DER -in CERT.RSA -text -noout -print_certs

其中CERT.RSA 表示的是文件CERT.RSA ,如果不是在当前文件夹中,应该填写CERT.RSA 的相对路径或者绝对路径。

可以用一张图来解释签名的过程:

安卓安装包签名_笔记签名验证

安装校验过程。

    我们从激活成功教程 sign.apk的过程来讲解校验的过程。首先由于v1是针对单一文件进行提取摘要的方式进行校验。

1.假如,我们破坏或者修改了apk中的某一个文件,那么我们必须修改MANIFEST.MF中的对应文件的摘要值,才能通过sdk对MANIFEST.MF的校验。

2.就算我们修改某个文件之后,并且修改了对应的MANIFEST.MF里面的摘要之后,由于CERT.SF中保存的是未修改之前的MANIFEST.MF中每个条目的SHA1之后的Base64编码值,因此前后比对,不一样。第二步对CERT.SF的校验,也不会通过。只有我们在修改MANIFEST.MF 摘要的同时,也修改CERT.SF对应条目的摘要值,才能通过第二步对CERT.SF的检测。

3前面两步通过伪装修改的方式对MANIFEST.MF和CERT.SF的校验都通过了的话,那么第三步CERT.RSA 的校验,就不可能伪装了,因为CERT.RSA 使用的是开发者的私钥信息进行的签名。用户无法获得其私钥信息,没法伪装。

v1版本签名下的多渠道包实现   

    既然上面的签名校验方式,不允许我们对apk解压之后的某个文件的修改。  我们就可以不破坏这种校验机制增加文件,来记录apk包的渠道信息。或者利用zip的文件格式来做文章存储我们的渠道信息。市面上有2种对v1签名生成多渠道包的方式。

方式1:们可以在不改变原来apk中任何单个文件的情况下,通过对apk增加文件的方式来记录相关的渠道信息。实现多渠道打包。

安卓安装包签名_笔记签名验证

我们可以在META-INF,或者apk包解压的任何文件夹位置添加一个我们自己的文件,文件名称如上面channel_xiaomi.txt,以文件名称作为渠道名,然后再重新生成apk的 zip文件。因为上面的MANIFEST.MF ,CERT.SF ,CERT.RSA是对apk解压之后的每个单独文件进行校验,但是我们增减的channel_xiaomi.txt是在生成渠道包之后,重新加入进去的,所以android系统安装apk的时候,我们增加的channel_xiaomi.txt并不在我们android系统校验的范围内,我们就可以在app内,读取这个文件的名称来获取对应的渠道。这里主要耗费的时间是对apk解压之后生成channel_xxx.txt的空文件,然后重新打包成.apk文件。

方式二:利用zip文件的文件格式,我们可以在文件最后的部分的comment(注释)中加入自己的渠道信息,然后再app中去读去zip文件的comment里面的内容,读去到对应的渠道号。这里主要是对zip文件的操作。

V2签名方案

         Android 7.0(Nougat)引入一项新的应用签名方案APK Signature Scheme v2,它是一个对全文件进行签名的方案,能提供更快的应用安装、对未授权APK文件的更改提供更多保护,在默认情况下,Android Gradle 2.2.0插件会使用APK Signature Scheme v2和传统签名方案来签署你的应用。

        目前该方案不是强制性的,在 build.gradle 添加 v2SigningEnabled false ,就能使用传统签名方案来签署我们的应用(见下面的代码片段)

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

      APK 签名方案 v2 是一种全文件签名方案,该方案能够发现对 APK 的受保护部分进行的所有更改,从而有助于加快验证速度并增强完整性保护。使用 APK 签名方案 v2 进行签名时,会在 APK 文件中插入一个 APK签名分块,该分块位于“ZIP 中央目录”部分之前并紧邻该部分。在“APK 签名分块”内,v2 签名和签名者身份信息会存储在 APK 签名方案 v2 分块中。

签名前和签名后的 APK

新的签名方案会在ZIP文件格式的 Central Directory 区块所在文件位置的前面添加一个APK Signing Block区块。整个APK(ZIP文件格式)会被分为以下四个区块: 1. Contents of ZIP entries(from offset 0 until the start of APK Signing Block) 2. APK Signing Block 3. ZIP Central Directory 4. ZIP End of Central Directory。

之前的渠道包生成方案是通过在META-INF目录下添加空文件,用空文件的名称来作为渠道的唯一标识,之前在META-INF下添加文件是不需要重新签名应用的,这样会节省不少打包的时间,从而提高打渠道包的速度。但在新的应用签名方案下META-INF已经被列入了保护区了,向META-INF添加空文件的方案会对区块1、3、4都会有影响,v2签名方案签署的应用经过我们旧的生成渠道包方案处理后,在安装时会报以下错误:

Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES:

Failed to collect certificates from base.apk: META-INF/CERT.SF indicates base.apk is signed using APK Signature Scheme v2, but no such signature was found. Signature stripped?]

目前V1签名另外一种比较流行的往APK中添加ZIP Comment,生成多渠道包的方案,也因为上述原因,无法在新的应用签名方案下进行正常工作。

既然v1签名生成多渠道包的方式对于v2不能使用,那么就需要找另外的出路了。

既然v2签名保护1,3,4块数据区,不能对1,3,4区快的数据做修改,那么就可以在2 数据区 Apk Signing block做修改,在这块数据加入我们的渠道信息。

APK 签名分块

为了保持与 v1 APK 格式向后兼容,v2 及更高版本的 APK 签名会存储在“APK 签名分块”内,该分块是为了支持 APK 签名方案 v2 而引入的一个新容器。在 APK 文件中,“APK 签名分块”位于“ZIP 中央目录”(位于文件末尾)之前并紧邻该部分。

该分块包含多个“ID-值”对,所采用的封装方式有助于更轻松地在 APK 中找到该分块。APK 的 v2 签名会存储为一个“ID-值”对,其中 ID 为 0x7109871a

数据 字节数 描述
size of blcok 8个字节 除此字段外 block的总长度
id-value-pairs 8个字节 此id与value 数据的总长度
id 4个字节 id数据
value n个字节 value数据
size of  block 8个字节 与第一个字段相同
magic 16个字节 魔数,标记block的数据格式

在解析 APK 时,首先要通过以下方法找到“ZIP 中央目录”的起始位置:在文件末尾找到“ZIP 中央目录结尾”记录,然后从该记录中读取“中央目录”的起始偏移量。通过 magic 值,可以快速确定“中央目录”前方可能是“APK 签名分块”。然后,通过 size of block 值,可以高效地找到该分块在文件中的起始位置。在解译该分块时,应忽略 ID 未知的“ID-值”对.

验证

在 Android 7.0 及更高版本中,可以根据 APK 签名方案 v2+ 或 JAR 签名(v1 方案)验证 APK。更低版本的平台会忽略 v2 签名,仅验证 v1 签名。

APK 签名验证过程

通过上图可以看出新的应用签名方案的验证过程:

1. 寻找APK Signing Block,如果能够找到,则进行验证,验证成功则继续进行安装,如果失败了则终止安装

2. 如果未找到APK Signing Block,则执行原来的签名验证机制,也是验证成功则继续进行安装,如果失败了则终止安装。

在参考文章中,zip的文件格式中我们可以知道End of Central Directory的这块的数据格式,如下:

Offset Bytes Description
0 4 End of central directory signature = 0x06054b50 核心目录结束标记,固定为0x06054b50
4 2 Number of this disk 当前的磁盘编号
6 2 Disk where central directory starts 核心目录开始的磁盘编号
8 2 Number of central directory records on this disk 磁盘上所记录的核心目录数量
10 2 Total number of central directory records 核心目录的总数
12 4 Size of central directory (bytes) 核心目录的大小
16 4 Offset of start of central directory, relative to start of archive 核心目录开始位置相对于archive的偏移
20 2 Comment length (n) 注释的长度
22 n Comment 注释的内容

知道apk的文件结构,这样可以从apk(实质就是zip文件) EOCD,反推出Central Directory的位置,最后确定是否有APK signing Block,然后确认是否是v2签名,同时我们也可以在APK signing Block这块内容增加一个固定的id(不与ID 0x7109871a重复就行)-value对,来存放我们apk的channel信息,这样就不会破坏整个apk的签名信息,又可以增加我们的渠道信息。

在使用美团打包walle的时候,如果你的build-tools 版本较高的话,可能打出来的包,无法在Android P 上安装。因为 android p 需要 apksigningblock 的长度确保为 4096 的倍数。具体的解决方案在这里

V3签名方案

Android 9 支持 APK秘钥轮替,这使应用能够在 APK 更新过程中更改其签名密钥。为了实现轮替,APK 必须指示新旧签名密钥之间的信任级别。为了支持密钥轮替,google将 APK签名从 v2 更新为 v3,以允许使用新旧密钥。v3 在 APK 签名分块中添加了有关受支持的 SDK 版本和 proof-of-rotation 结构的信息。

APK 签名验证过程

参考文章:

APK 签名方案 v2  |  Android 开源项目  |  Android Open Source Project

zip文件格式

美团自动化打包实践

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/219073.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 三大运营商电话号码监测

    三大运营商电话号码监测Document

  • PHP情人:p十几天来学习hp第一天

    PHP情人:p十几天来学习hp第一天

  • VUE(相关简介及初始)

    1.什么是vueVue是一个数据驱动页面的一个框架,基于MVVM模式,M指的是数据,V值得是视图,VM是视图模型,将数据绑定视图上(双向绑定)这个框架着重于VM部分2.VUE诞生的背景近几年来

  • 安全帽识别前端与后端功能分析[通俗易懂]

    安全帽识别前端与后端功能分析[通俗易懂]近年来,监管部门对建筑工地的要求越来越高了,为保障工地现场人员安全,智慧工地解决方案增加了更多的管理方式,其中安全帽识别已经成为智慧工地的重要管理手段。安全帽识别是通过视频分析来检测工作人员是否佩戴安全帽,属于人…

  • Git创建远程分支并提交代码到远程分支[通俗易懂]

    Git创建远程分支并提交代码到远程分支[通俗易懂]1、可以通过gitbranch-r命令查看远端库的分支情况如图所示,远程仓库只有一个master分支2、从已有的分支创建新的分支(如从master分支),创建一个dev分支但此时并没有在远程仓库上创建分支如图所示还是只有一个master分支3、建立本地到远端仓库的链接–这样代码才能提交上去使用命令行gitpush–set-…

  • 详解C/C++中volatile关键字

    详解C/C++中volatile关键字一、volatile介绍volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。下面举例说明。在DSP开发中,经常需要等待某个事件的触发,所以经常会写出这样的程序:这段…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号