应用签名

Android目前支持两种应用签名方案:

  • V1方案,基于JAR签名的方案
  • V2方案,Android 7.0引入的方案

为了最大限度的提高兼容性,应同时采用V1和V2两种方案签名。

与只通过 v1 方案签名的应用相比,通过 v2 方案签名的应用能够更快速地安装到 Android Nougat 及更高版本的设备上。更低版本的 Android 平台会忽略 v2 签名,这就需要应用包含 v1 签名。

V1

问题:

  • V1签名不是对apk的整体的全面保护,有些数据它不保护,如ZIP元数据(描述zip的数据)
  • apk验证程序必须解压所有已经压缩的条目,这就需要花费很多的时间和内存

V1的验证方式

  1. 每个签名者均由包含 META-INF/xx.SF 和 META-INF/xx.RSA的jar条目来表示
  2. xx.SF 文件包含 META-INF/MANIFEST.MF 的全文件摘要和 META-INF/MANIFEST.MF 各个部分的摘要。需要验证 MANIFEST.MF 的全文件摘要。如果该验证失败,则改为验证 MANIFEST.MF 各个部分的摘要。
  3. 对于每个受完整性保护的 JAR 条目,META-INF/MANIFEST.MF 都包含一个具有相应名称的部分,其中包含相应条目未压缩内容的摘要。所有这些摘要都需要验证。
  4. 如果 APK 包含未在 MANIFEST.MF 中列出且不属于 JAR 签名一部分的 JAR 条目,APK 验证将会失败

META-INF文件夹解析

文件夹下有三个文件:

  • MANIFEST.MF:名称固定不能变
  • XX.RSA
  • XX.SF 后两个默认的名称是CERT,但是这个名字是可以修改的(通过keystore可以修改,貌似是keyAlias)。

MANIFEST.MF

保存了apk中除了METE-INF之外的所有文件的摘要信息。

整个的文件结构:

Manifest-Version: 1.0 Created-By: 创建者

Name: xxx SHA1-Digest: SHA-1 + Base64

摘要信息的值算法是:SHA-1 + Base64

如果更改了apk包中的某些文件,那么对用的MANIFEST.MF的信息也会改变。

在apk的安装过程中,如果更改后的文件摘要与MANIFEST.MF表中的摘要不匹配就会导致安装失败。但更改文件的同时也更改了MANIFEST.MF中对应的摘要信息,则会绕过这个维度的校验。

XX.SF

是在前一步生成的MANIFEST.MF的所有摘要信息(加上MANIFEST.MF文件本身)通过开发者的私钥使用SHA1-RSA + Base64编码产生新的摘要。

整个文件的结构:

Signature-Version: 1.0 SHA1-Digest-Manifest-Main-Attributes: RsH+8ih8p183k9Q4ABmKLR6jIHo=

SHA1-Digest-Manifest: MANIFEST.MF的摘要 Created-By: 创建者

安装时,通过XX.RSA中的公钥解密XX.SF的信息,就能得到做SHA1-RSA之前的摘要信息,那整个与MANIFEST.MF进行比对验证,就知道apk有没有被修改。

所以:

  • 即时破解者修改了程序内容并生成新的摘要信息,但没有私钥,是不能生成正确的XX.SF的
  • 如果用公钥对不正确的签名文件进行解密,生成的结果则无法与MANIFEST.MF对应

XX.RSA

保存了开发者公钥、数字签名、证书发布机构、有效期、所有者、签名算法等信息。安装程序再安装apk时对CERT.SF文件进行解密,所需要的公钥就是从CERT.RSA里提取出来的。

查看方法:

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

RSA1 vs MD5

V2

使用 APK 签名方案 v2 进行签名时,会在 APK 文件中插入一个 APK 签名分块,该分块位于“ZIP 中央目录”部分之前并紧邻该部分。在“APK 签名分块”内,v2 签名和签名者身份信息会存储在 APK 签名方案 v2 分块中。

V2受完整性保护的内容

V2保护上图中的1、3、4部分的完整性,以及2部分包含的“APK 签名方案v2分块”中的signed data分块的完整性。

第 1、3 和 4 部分的完整性通过其内容的一个或多个摘要来保护,这些摘要存储在 signed data 分块中,而这些分块则通过一个或多个签名来保护。

防回滚保护

黑客可能会在支持v2签名的android平台上,对v2签名的apk做绕过v2的机制,采用v1的验证方式。

所以,为了防止这种供攻击,采用如下方式:

带 v2 签名的 APK 如果还带 v1 签名,其 META-INF/*.SF 文件的主要部分中必须包含 X-Android-APK-Signed 属性,该属性的值是一组以英文逗号分隔的apk前方案id。

那么在验证V1签名时,如果apk没有这些对应的签名,那么apk验证程序必须拒绝这些apk。此项保护依赖于内容 META-INF/*.SF 文件受 v1 签名保护这一事实。

攻击者可能会试图从“APK 签名方案 v2 分块”中删除安全系数较高的签名。为了防范此类攻击,对 APK 进行签名时使用的签名算法 ID 的列表会存储在通过各个签名保护的 signed data 分块中。

V2验证流程

  1. 找到“APK签名分块”并验证
  2. 找到“APK签名分块”中的apk签名方案V2分块。如果v2分块存在,则继续,否则走v1方案验证
  3. 对v2分块中的每个signer执行以下操作:。。。
  4. 如果找到了至少一个 signer,并且对于每个找到的 signer,第 3 步都取得了成功,APK 验证将会成功。

results matching ""

    No results matching ""