Apk打包流程和签名算法的原理

一、Apk打包流程

既点击Andorid Studio的Build按钮后发生了什么?
Android 的包文件 APK 分为两个部分:代码和资源,所以打包方面也分为资源打包和代码打包两个方面,下面就来分析资源和代码的编译打包原理。

APK 整体的的打包流程如下图所示:


image.png

具体说来:

  • 通过 AAPT 工具进行资源文件(包括 AndroidManifest.xml、布局文件、
    各种 xml 资源等)的打包,生成 R.java 文件。
  • 通过 AIDL 工具处理 AIDL 文件,生成相应的 Java 文件。
  • 通过 Java Compiler 编译 R.java、Java 接口文件、Java 源文件,生成.class
    文件。
  • 通过 dex 命令,将.class 文件和第三方库中的.class 文件处理生成
    classes.dex,该过程主要完成 Java 字节码转换成 Dalvik 字节码,压缩常
    量池以及清除冗余信息等工作。
  • 通过 ApkBuilder 工具将资源文件、DEX 文件打包生成 APK 文件。
  • 通过 Jarsigner 工具,利用 KeyStore 对生成的 APK 文件进行签名。
  • 如果是正式版的 APK,还会利用 ZipAlign 工具进行对齐处理,对齐的过
    程就是将 APK 文件中所有的资源文件距离文件的起始距位置都偏移 4 字
    节的整数倍,这样通过内存映射访问 APK 文件的速度会更快,并且会减
    少其在设备上运行时的内存占用。

二、Apk组成部分

  • dex:最终生成的 Dalvik 字节码。
  • res:存放资源文件的目录。
  • asserts:额外建立的资源文件夹。
  • lib:如果存在的话,存放的是 ndk 编出来的 so 库。
  • META-INF:存放签名信息
    MANIFEST.MF(清单文件):其中每一个资源文件都有一个 SHA-256-Digest 签名,MANIFEST.MF 文件的 SHA256(SHA1)并base64 编码的结果即为 CERT.SF中的 SHA256-Digest-Manifest 值。
    CERT.SF(待签名文件):除了开头处定义的 SHA256(SHA1)-Digest-Manifest值,后面几项的值是对 MANIFEST.MF 文件中的每项再次 SHA256 并 base64 编码后的值。
    CERT.RSA(签名结果文件):其中包含了公钥、加密算法等信息。首先对前一步生成的 MANIFEST.MF 使用了 SHA256(SHA1)-RSA 算法,用开发者私钥签名,然后在安装时使用公钥解密。最后,将其与未加密的摘要信息(MANIFEST.MF文件)进行对比,如果相符,则表明内容没有被修改。
  • androidManifest:程序的全局清单配置文件。
  • resources.arsc:编译后的二进制资源文件

三、签名算法的原理

为什么要签名?
  • 确保 Apk 来源的真实性。
  • 确保 Apk 没有被第三方篡改。
什么是签名?

在 Apk 中写入一个“指纹”。指纹写入以后,Apk 中有任何修改,都会导致这个指纹无效,Android 系统在安装 Apk 进行签名校验时就会不通过,从而保证了安全性。

数字摘要

对一个任意长度的数据,通过一个 Hash 算法计算后,都可以得到一个固定长度的二进制数据,这个数据就称为“摘要”。
补充:

  • 散列算法的基础原理:将数据(如一段文字)运算变为另一固定长度值。
  • SHA-1:在密码学中,SHA-1(安全散列算法 1)是一种加密散列函数,它接受输入并产生一个 160 位(20 字节)散列值,称为消息摘要 。
  • MD5:MD5 消息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个 128 位(16 字节)的散列值(hash value),用于确保信息传输完整一致。
  • SHA-2:名称来自于安全散列算法 2(英语:Secure Hash Algorithm 2)的缩写,一种密码散列函数算法标准,其下又可再分为六个不同的算法标准,包括了:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。
    特征:
  • 唯一性
  • 固定长度:比较常用的 Hash 算法有 MD5 和 SHA1,MD5 的长度是 128
    拉,SHA1 的长度是 160 位。
  • 不可逆性
签名和校验的主要过程

签名就是在摘要的基础上再进行一次加密,对摘要加密后的数据就可以当作数字签名。
签名过程:

  • 1、计算摘要:通过 Hash 算法提取出原始数据的摘要。
  • 2、计算签名:再通过基于密钥(私钥)的非对称加密算法对提取出的摘要进行加密,加密后的数据就是签名信息。
  • 3、写入签名:将签名信息写入原始数据的签名区块内。
    校验过程:
  • 1、首先用同样的 Hash 算法从接收到的数据中提取出摘要。
  • 2、解密签名:使用发送方的公钥对数字签名进行解密,解密出原始摘要。
  • 3、比较摘要:如果解密后的数据和提取的摘要一致,则校验通过;如果数据被第三方篡改过,解密后的数据和摘要将会不一致,则校验不通过。
数字证书

如何保证公钥的可靠性呢?答案是数字证书,数字证书是身份认证机构
(Certificate Authority)颁发的,包含了以下信息:

  • 证书颁发机构
  • 证书颁发机构签名
  • 证书绑定的服务器域名
  • 证书版本、有效期
  • 签名使用的加密算法(非对称算法,如 RSA)
  • 公钥等
    接收方收到消息后,先向 CA 验证证书的合法性,再进行签名校验。
    注意:Apk 的证书通常是自签名的,也就是由开发者自己制作,没有向 CA 机构申请。Android 在安装 Apk 时并没有校验证书本身的合法性,只是从证书中提取公钥和加密算法,这也正是对第三方 Apk 重新签名后,还能够继续在没有安装这个 Apk 的系统中继续安装的原因。
keystore 和证书格式

keystore 文件中包含了私钥、公钥和数字证书。根据编码不同,keystore 文件分
为很多种,Android 使用的是 Java 标准 keystore 格式 JKS(Java Key Storage),
所以通过 Android Studio 导出的 keystore 文件是以.jks 结尾的。
keystore 使用的证书标准是 X.509,X.509 标准也有多种编码格式,常用的有两
种:pem(Privacy Enhanced Mail)和 der(Distinguished Encoding Rules)。
jks 使用的是 der 格式,Android 也支持直接使用 pem 格式的证书进行签名。
两种证书编码格式的区别:

  • DER(Distinguished Encoding Rules)
    二进制格式,所有类型的证书和私钥都可以存储为 der 格式。
  • PEM(Privacy Enhanced Mail)
    base64 编码,内容以-----BEGIN xxx----- 开头,以-----END xxx----- 结尾。
jarsigner 和 apksigner 的区别

Android 提供了两种对 Apk 的签名方式,一种是基于 JAR 的签名方式,另一种是基于 Apk 的签名方式,它们的主要区别在于使用的签名文件不一样:jarsigner使用 keystore 文件进行签名;apksigner 除了支持使用 keystore 文件进行签名外,还支持直接指定 pem 证书文件和私钥进行签名。

在签名时,除了要指定 keystore 文件和密码外,也要指定 alias 和 key 的密码,这是为什么呢?

keystore 是一个密钥库,也就是说它可以存储多对密钥和证书,keystore 的密码是用于保护 keystore 本身的,一对密钥和证书是通过 alias 来区分的。所以jarsigner 是支持使用多个证书对 Apk 进行签名的,apksigner 也同样支持。

Android Apk V1 签名原理
  • 1、解析出 CERT.RSA 文件中的证书、公钥,解密 CERT.RSA 中的加密数
    据。
  • 2、解密结果和 CERT.SF 的指纹进行对比,保证 CERT.SF 没有被篡改。
  • 3 、 而 CERT.SF 中 的 内 容 再 和 MANIFEST.MF 指 纹 对 比 , 保 证MANIFEST.MF 文件没有被篡改。
  • 4、MANIFEST.MF 中的内容和 APK 所有文件指纹逐一对比,保证 APK没有被篡改。

你可能感兴趣的:(Apk打包流程和签名算法的原理)