准备知识

要理解Android的签名机制,首先要熟悉数字签名技术,可以参考我的另一篇文章:《信息安全的护城河:数字证书与数字签名技术》

Android签名机制

签名工具
Android应用的签名工具有两种:jarsigner和signapk。它们的签名算法没什么区别,主要是签名使用的文件不同。
jarsigner:jdk自带的签名工具,可以对jar进行签名。使用keystore文件进行签名。生成的签名文件默认使用keystore的别名命名。
signapk:Android sdk提供的专门用于Android应用的签名工具。使用pk8、x509.pem文件进行签名。其中pk8是私钥文件,x509.pem是含有公钥的文件。生成的签名文件统一使用“CERT”命名。
既然这两个工具都是给apk签名的,那么keystore文件和pk8,x509.pem他们之间是不是有什么联系呢?答案是肯定的,他们之间是可以转化的,这里就不再分析如何进行转化,网上的例子很多。
还有一个需要注意的知识点,如果我们查看一个keystore文件的内容,会发现里面包含有一个MD5和SHA1摘要,这个就是keystore文件中私钥的数据摘要,这个信息也是我们在申请很多开发平台账号时需要填入的信息。
签名过程
首先我们任意选取一个签名后的APK(SMSSDKSample-release.apk)解压:
在META-INF文件夹下有三个文件:MANIFEST.MF、CERT.SF、CERT.RSA。它们就是签名过程中生成的文件,姑且叫他们“签名三兄弟”吧,把它们搞清楚了,你就精通签名了。
1.MANIFEST.MF
该文件中保存的内容其实就是逐一遍历apk中的所有条目,如果是目录就跳过,如果是一个文件,就用SHA1(或者SHA256)消息摘要算法提取出该文件的摘要然后进行BASE64编码后,作为“SHA1-Digest”属性的值写入到MANIFEST.MF文件中的一个块中。该块有一个“Name”属性,其值就是该文件在apk包中的路径。
2.CERT.SF
SHA1-Digest-Manifest-Main-Attributes:对MANIFEST.MF头部的块做SHA1(或者SHA256) 后再用Base64编码
SHA1-Digest-Manifest:对整个MANIFEST.MF文件做SHA1(或者SHA256) 后再用Base64编码
SHA1-Digest:对MANIFEST.MF的各个条目做SHA1(或者SHA256) 后再用Base64编码
对于SHA1-Digest值的验证可以手动进行,将MANIFEST.MF中任意一个块的内容复制并保存在一个新的文档中,注意文末需要加两个换行(这是由signapk的源码决定的)
保存文件,然后对该文件计算其SHA1值后使用Base64编码:
得到的值就是CERT.SF 中相应条目的SHA1-Digest的值:
3.CERT.RSA
这里会把之前生成的 CERT.SF文件,用私钥计算出签名, 然后将签名以及包含公钥信息的数字证书一同写入  CERT.RSA  中保存。这里要注意的是, Android APK中的CERT.RSA证书是自签名的,并不需要这个证书是第三方权威机构发布或者认证的,用户可以在本地机器自行生成这个自签名证书。Android 目前不对应用证书进行 CA 认证。
Tips:所谓自签名证书是指自己给自己颁发的证书,即公钥证书中Issuer(发布者)和Subject(所有者)是相同的。当然,APK也可以采用由CA颁发私钥证书进行签名。采用非自签名时,最终APK的公钥证书中就会包含证书链,并且会存在多余一个证书,证书间通过Issuer与Subject进行关联,Issuer负责对Subject进行认证。当安装APK时,系统只会用位于证书链中最底层的证书对APK进行校验,但并不会验证证书链的有效性。在Https通信中使用自签名证书时浏览器的显示效果:
这里我们看到的都是二进制文件,因为RSA文件加密了,所以我们需要用openssl命令才能查看其内容:
openssl pkcs7 -inform DER -in /Users/jackie/Downloads/apk签名机制/SMSSDKSample-release_new/original/META-INF/DEMOKEY_.RSA -text -noout -print_certs
关于这些信息,可以看下面这张图:
综上所述,一个完整的签名过程如下所示:
签名验证过程
签名验证是发生在apk的安装过程中,一共分为三步:
(1)检查apk中包含的所有文件,对应的摘要值与MANIFEST.MF文件中记录的值一致。
(2)使用证书文件(RSA文件)检验签名文件(SF文件)没有被修改过。
(3)使用签名文件(SF文件)检验MF文件没有被修改过。
综上所述,一个完整的签名验证过程如下所示:
为什么使用这样的签名流程呢?
我们假设一下,首先,如果你改变了apk包中的任何文件,那么在apk安装校验时,改变后的文件摘要信息与MANIFEST.MF的检验信息不同,于是验证失败,程序就不能成功安装。
其次,如果你对更改过的文件相应的算出新的摘要值,然后更改MANIFEST.MF文件里面对应的属性值,那么必定与CERT.SF文件中算出的摘要值不一样,照样验证失败。
最后,如果你还不死心,继续计算MANIFEST.MF的摘要值,相应的更改CERT.SF里面的值,那么数字签名值必定与CERT.RSA文件中记录的不一样,还是失败。
那么能不能继续伪造数字签名呢?不可能,因为没有数字证书对应的私钥。
APK Signature Scheme v2
在 Android 7.0 Nougat 中引入了全新的 APK Signature Scheme v2。
APK 签名方案 v2 是一种 全文件签名方案,该方案能够发现对 APK 的受保护部分进行的所有更改,从而有助于加快验证速度并增强完整性保证。
原因
为什么谷歌要做这个事情呢?第一点毋庸置疑,肯定是处于安全性的考虑,之前的校验方式开发者可以在打包之后对apk做很多处理,第二为了性能考虑,安装校验的时候不需要再解压缩校验,从而提升安装速度。
v2带来了什么变化
由于在 v1 仅针对单个ZIP条目进行验证,因此,在 APK 签署后可进行许多修改 - 可以移动甚至重新压缩文件。事实上,编译过程中要用到的 zipalign 工具就是这么做的,它用于根据正确的字节限制调整 ZIP 条目,以改进运行时性能。而且我们也可以利用这个东西,在打包之后修改META-INF目录下面的内容,或者修改Zip的注释来实现多渠道的打包,在v1签名中都可以校验通过。
v2 签名将验证归档中的所有字节,而不是单个 ZIP 条目,因此,在签署后无法再运行 zipalign(必须在签名之前执行)。正因如此,现在,在编译过程中,Google将压缩、调整和签署合并成一步完成。
新的签名方案就是一种扩展的Zip格式
使用 APK 签名方案 v2 进行签名时,会在 APK 文件中插入一个 APK 签名分块,该分块位于“ZIP 中央目录”部分之前并紧邻该部分。在“APK 签名分块”内,v2 签名和签名者身份信息会存储在 APK 签名方案 v2 分块中。
受完整性保护的内容
为了保护APK内容,整个APK(zip文件格式)被分为以下4个区块:
  • ZIP 条目的内容(从偏移量 0 处开始一直到“APK 签名分块”的起始位置)
  • APK 签名分块
  • ZIP 中央目录
  • ZIP 中央目录结尾
APK 签名方案 v2 负责保护第 1、3、4 部分的完整性,以及第 2 部分包含的“APK 签名方案 v2 分块”中的 signed data 分块的完整性。
第 1、3 和 4 部分的完整性通过其内容的一个或多个摘要来保护,这些摘要存储在 signed data 分块中,而这些分块则通过一个或多个签名来保护。
新旧签名方案的兼容
新的签名格式向后兼容,因此,使用这种新格式签名的 APK 可在更低版本的 Android 设备上进行安装(会直接忽略添加到 APK 的额外数据),但前提是这些 APK 还带有 v1 签名。
验证程序会对照存储在“APK 签名分块”中的 v2 签名对 APK 的全文件哈希进行验证。该哈希涵盖除“APK 签名分块”(其中包含 v2 签名)之外的所有内容。在“APK 签名分块”以外对 APK 进行的任何修改都会使 APK 的 v2 签名作废。v2 签名被删除的 APK 也会被拒绝,因为 v1 签名指明相应 APK 带有 v2 签名,所以 Android Nougat 及更高版本会拒绝使用 v1 签名验证 APK。这就是所谓的“防回滚保护”。
Tips:攻击者可能会试图在支持对带 v2 签名的 APK 进行验证的 Android 平台上将带 v2 签名的 APK 作为带 v1 签名的 APK 进行验证。为了防范此类攻击,带 v2 签名的 APK 如果还带 v1 签名,其 META-INF/*.SF 文件的主要部分中必须包含 X-Android-APK-Signed 属性。该属性的值是一组以英文逗号分隔的 APK 签名方案 ID(v2 方案的 ID 为 2)。在验证 v1 签名时,对于此组中验证程序首选的 APK 签名方案(例如,v2 方案),如果 APK 没有相应的签名,APK 验证程序必须要拒绝这些 APK。此项保护依赖于内容 META-INF/*.SF 文件受 v1 签名保护这一事实。
新签名方案v2对现存的渠道包生成工具的影响
之前的渠道包生成方案是通过在META-INF目录下添加空文件,用空文件的名称来作为渠道的唯一标识。但在新的应用签名方案下META-INF已经被列入了保护区了,向META-INF添加空文件的方案会对区块1、3、4都会有影响。
另外一种比较流行的渠道包快速生成方案(修改Zip的注释)也因为上述原因,无法在新的应用签名方案下进行正常工作。
如果新签名方案v2后续改成强制要求,那现有的生成渠道包的方式就会无法工作,难道要退回到解放前吗?
从上面的描述可以看到,区块1、3、4都是被保护的,任何针对这3个区块的修改都会被新签名方案v2检测到,但区块2(APK Signing Block)是不受签名校验规则保护的。美团的新一代打渠道包工具Walle就是往区块2写入一个自定义的ID-value,在App运行阶段,可以通过ZIP的EOCD(End of central directory)、Central directory等结构中的信息(涉及ZIP格式的相关知识,这里不做展开描述)找到我们自己添加的ID-value,从而实现获取渠道信息的功能,来应对新签名方案v2的。
知识点梳理
1.公钥密码体制:
(1)公钥密码体制的公钥和算法都是公开的,私钥是保密的。一方加密的数据只能由另一方解密。
(2)公钥加密、私钥解密,称为“加密”;私钥加密、公钥解密,称为“签名”。公钥密码体制是目前唯一同时具备了加密与签名功能的密码体制。
2.消息摘要、数字签名、数字证书的含义:
(1)消息摘要又称数字指纹,就是对一个消息做SHA/MD5算法,这个值是唯一的;
(2)一个高效的数字签名技术 = 消息摘要技术 + 非对称加密技术(RSA算法)
(3)数字证书中包含了证书持有者的信息、持有者的公钥、证书签发机构(CA)的信息、CA机构对证书本身的签名信息以及其他一些信息,主要用于解决公钥的安全发放问题
(4)在Android签名之后,其中SF就是签名文件,RSA就是证书文件,我们可以用openssl来查看RSA文件中的证书信息和公钥信息
(5)Android APK中的CERT.RSA证书是自签名的,并不需要这个证书是第三方权威机构发布或者认证的
3.Android中的签名有两种方式:jarsigner和signapk。这两种方式的区别是:
(1)jarsigner签名时,需要的是keystore文件,而signapk签名的时候是pk8,x509.pem文件
(2)jarsigner签名之后的SF和RSA文件名默认是keystore的别名,而signapk签名之后文件名是固定的:CERT
(3)keystore文件和pk8,x509.pem文件之间可以互相转化
4.新签名方案v2:
(1)v2是一种全文件签名方案,对整个zip文件(包括zip元数据)进行签名
(2)v2方案下,zipalign需要在签名之前执行
(3)v2的签名工具-apksigner,位于sdk的build-tools目录下,但由于v2是Android7.0之后才推出的,所以只有版本>25的sdk中才能找到apksigner.jar
(4)为了兼容7.0以下设备,需要同时使用v1和v2签名。此时,在7.0及以上设备中只会验证v2签名,如果试图删除v2签名保留v1签名,系统同样会验证不通过,即“防回滚保护”;而在7.0以下设备中,则只会验证v1签名

Android签名机制相关推荐

  1. android digest 认证,探究 Android 签名机制和原理

    背景 最近在调研一个测试工具的使用,在使用中发现被测试工具处理过的apk文件经安装后打开就会崩溃,分析崩溃日志后原因是签名不一致导致的. 说到Android中的签名,可能大家都知道签名的目的就是为了保 ...

  2. Android学习笔记——Android 签名机制详解

    Android 签名机制详解 近期由于工作需要在学习 Android 的签名机制,因为没有现成资料,只能通过开发者文档和阅读博客的方式对 Android 签名机制进行大致了解.过程中查阅到的资料相对零 ...

  3. Android签名机制及PMS中校验流程(雷惊风)

    @Android签名机制及PMS中校验流程(雷惊风) 网上看到一篇比较好的关于Android签名的文章,但是文章链接不安全,不知道哪天会不会找不到了,而且需要关注才能查看完整版,所以在这里记录一下,原 ...

  4. 【Android签名机制详解】二:Android V1、V2、V3、V4签名方案

    前言 书接上回[Android签名机制详解]一:密码学入门,在了解了消息摘要.非对称加密.数字签名.数字证书的基本概念后,我们趁热打铁.直奔主题,讲解签名在Android中的实际应用. 基础知识 An ...

  5. Android签名机制之---签名验证过程详解

    一.前言 今天是元旦,也是Single Dog的嚎叫之日,只能写博客来祛除寂寞了,今天我们继续来看一下Android中的签名机制的姊妹篇:Android中是如何验证一个Apk的签名.在前一篇文章中我们 ...

  6. Android签名机制介绍:生成keystore.签名.查看签名信息等方法

    为什么80%的码农都做不了架构师?>>>    Android独有的安全机制,除了权限机制外,另外一个就是签名机制了.签名机制主要用在以下两个主要场合起到其作用:升级App和权限检查 ...

  7. Android签名机制:生成keystore、签名、查看签名信息

    2019独角兽企业重金招聘Python工程师标准>>> Android独有的安全机制,除了权限机制外,另外一个就是签名机制了.签名机制主要用在以下两个主要场合起到其作用:升级App和 ...

  8. Android 签名机制原理解析和V1 、V2签名区别

    一.什么是签名? 是确保消息来源的真实性 是确保消息不会被第三方篡改 1.基本信息基础必备 1.1 消息摘要 消息摘要,又称数字摘要 或 数字指纹.  简单来说,消息摘要就是在消息数据上,执行一个单向 ...

  9. Android签名机制-签名过程详解

    目录 一.前言 二.准备知识 1.数据摘要 2.签名文件和证书 3.jarsign和signapk工具 4.keystore文件和pk8,x509.pem文件的区别 5.手动的签名Apk包 三.分析A ...

最新文章

  1. 【转】复盘一次失败的技术面试后,我成功拿到了5个offer
  2. C语言Kruskal 算法 (MST)(附完整源码)
  3. project-population
  4. 代码逆流成河,深入C++如何又快又有效?
  5. mysql字符串和数字的互相转换
  6. Baum-WELCH和vertibe解码算法
  7. 手写java_手写java锁
  8. 怎么用c语言解四元方程,求四元一次方程组的解
  9. 分享ASP.NET视频系列教程——第十九讲 ASP.NET内置的AJAX
  10. 一步步教您搞定讯飞语音识别 | 寻找C站宝藏
  11. 1.一个人赶着鸭子去每个村庄卖,每经过一个村子卖去所赶鸭子的一半又一只。 这样他经过了七个村子后还剩两只鸭子,问他出发时共赶多少只鸭子?经过每个村子卖出多少只鸭子?2.角谷定理。
  12. python 004 __小斌文档 | 判断和循环
  13. 链塔区块链数据平台周报:新增富豪榜、项目点评、收藏等功能 | 链塔数据
  14. uni-app开发模式中的选择图片(uni.chooseImage)、上传图片(uni.uploadFile)、图片预览(uni.previewImage)
  15. Word打开docx文件报错
  16. 【C++】C++11 新特性
  17. 【2022国赛模拟】摆(bigben)——行列式、杜教筛
  18. linux grub 编辑器,KGRUBEditor: 可视化的 GRUB 编辑器
  19. 外卖返利系统电影吃喝玩乐团购返利系统外卖探探外卖券儿外卖cps系统saas源码
  20. 统计学——线性回归公式推导

热门文章

  1. 如何禁止别人使用U盘的方法 - 并不需要使用专业软件
  2. 精益画布_听过「商业画布」,那么「精益画布」呢?
  3. 天鹰优化器(AO)——2021最新优化算法
  4. linux raid卡缓存,RAID卡的缓存与磁盘自带的缓存的关系
  5. mysql中的split函数_mysql中的split函数
  6. mysql like escape_mysql like语句用法详解 含通配符使用方法
  7. 中国CAE行业现状及发展前景分析
  8. windows操作系统有哪些版本
  9. 在无界面的Linux服务器上下载百度网盘文件
  10. JS工具函数大全,值得一看