Android 签名之Signature Version V1 和 V2 探索

发表于:2018-09-05 10:45:56      发布在:Android      评论:0 条评论

记录之前写的一篇总结。

V1:V1是Android7.0之前的签名方式,使用jar Signature方式对APK进行签名打包,jar Signature来自JDK。APK进行签名时会生成一个META-INF文件夹,里面有三个文件:MANIFEST.MFCERT.RSACERT.SF,是用来记录签名信息的。

除了上述三个文件,其他的文件都会对文件内容做一次SHA1算法,就是计算出文件的摘要信息,然后用Base64进行编码。比如AndroidManifest.xml文件,就会对它进行编码生成SHA-1值,把这个SHA-1值用Base64转化网站转化回去,就是MANIFEST.MF文件中记录的条目值。

因此,MANIFEST.MF中存储的是:逐一遍历里面的所有条目,如果是目录就跳过,如果是一个文件,就用SHA1(或者SHA256)消息摘要算法提取出该文件的摘要然后进行BASE64编码后,作为“SHA1-Digest”属性的值写入到MANIFEST.MF文件中的一个块中。该块有一个“Name”属性,其值就是该文件在apk包中的路径。

不再详细累述,CERT.SF文件做了什么工作:

1.计算这个MANIFEST.MF文件的整体SHA1值,再经过BASE64编码后,记录在CERT.SF主属性块(在文件头上)的“SHA1-Digest-Manifest”属性值值下。

2.逐条计算MANIFEST.MF文件中每一个块的SHA1,并经过BASE64编码后,记录在CERT.SF中的同名块中,属性的名字是“SHA1-Digest”。

CERT.RSA是一个满足PKCS7格式的文件:它会把之前生成的 CERT.SF文件,用私钥计算出签名, 然后将签名以及包含公钥信息的数字证书一同写入CERT.RSA中保存。

总结:V1加密签名后,如果APK文件被篡改后,在APK安装校验时,改变后的文件摘要信息与MANIFEST.MF的检验信息不同,于是验证失败,程序就不能成功安装。

如果你对更改的过的文件相应的算出新的摘要值,然后更改MANIFEST.MF文件里面对应的属性值,那么必定与CERT.SF文件中算出的摘要值不一样,照样验证失败。

如果不死心继续计算MANIFEST.MF的摘要值,相应的更改CERT.SF里面的值,那么数字签名值必定与CERT.RSA文件中记录的不一样,还是失败。

所以,重新打包后的应用程序能再Android设备上安装,必须对其进行重签名。

V2:Android7.0推出了V2签名方式,使用Full Apk Signature方式对APK进行签名打包。

经过对V1的详细介绍,V2就简单明了了。V1是验证单个的ZIP条目,而V2则是验证压缩文件的所有字节码。因此,在签名完成后无法再更改(包括zipalign)。因此,现在在编译过程中,压缩、调整和签署合并成一步完成。好处是,更安全而且新的签名可缩短在设备上进行验证的时间(不需要费时地解压缩然后验证),从而加快应用安装速度。当然只在Android7.0以上的手机才会使用这种验证方式。

总结:

选择V1还是V2?

只选择V1,还是依照旧的签名方式,不会有任何影响,只是在Android7.0以上的手机上不会使用更安全的验证方式。

只选择V2,在Android7.0以上的手机没问题,但是由于7.0以下的系统没有这种新的验证方式,因此会提示未安装。

同时选择V1和V2,在Android7.0以下的手机会使用V1验证,7.0以上的会使用V2方式验证,因此都没问题。

新的问题(多渠道打包)

由于Android市场众多,因此需要标记不同的渠道包。

目前使用的方案是:使用V1签名方式,美团Python脚本批量打包,它的原理就是生成一个全新的文件,把APK进行解压遍历复制进去,复制中通过在META-INF目录下添加空文件,用空文件的名称来作为渠道的唯一标识,之前在META-INF下添加文件是不需要重新签名应用的,因此批量打出的包在Android上是可以校验通过的。

但是如果使用的V2方式,在新的应用签名方案下META-INF已经被列入了保护区了,那么Python脚本批量打出的包就会造成Android7.0上校验不通过,这便是之前我们遇到的问题。

虽然只使用V1签名验证不会影响什么,但V2是谷歌爸爸推荐的签名方式,肯定是要慢慢用起来的,一路高歌走向安全规范化的道路。

美团推出了针对V2的新一套批量打包方式,并生成了插件,可以使用Gradle快速集成。

Walle(瓦力)https://github.com/Meituan-Dianping/walle

walle.png

可扩展的APK Signature Scheme v2 Block

V2的签名信息是以ID(0x7109871a)的ID-value来保存在这个区块中,通过Android源代码可以看出Android是通过查找ID为 APK_SIGNATURE_SCHEME_V2_BLOCK_ID = 0x7109871a 的ID-value,来获取APK Signature Scheme v2 Block,对这个区块中其他的ID-value选择了忽略。

因此美团是通过提供一个自定义的ID-value并写入该区域,从而为快速生成渠道包服务,每打一个渠道包只需复制一个APK,然后在APK中添加一个ID-value即可。

所以,我们可以考虑采用这用新的方式来打渠道包了。

参考链接:

https://tech.meituan.com/android-apk-v2-signature-scheme.html

http://blog.csdn.net/u011904605/article/details/52058971

http://www.jianshu.com/p/a27783a713f2

http://www.jianshu.com/p/e1e2fd05bb62

关于上次分享的APK加壳概念:

一、什么是加壳?

加壳是在二进制的程序中植入一段代码,在运行的时候优先取得程序的控制权,做一些额外的工作。大多数病毒就是基于此原理。是应用加固的一种手法对原始二进制原文进行加密/隐藏/混淆。

示例.png

1、需要加密的Apk(源Apk)

2、壳程序Apk(负责解密Apk工作)

3、加密工具(将源Apk进行加密和壳Dex合并成新的Dex)

加壳程序就是把要加壳的apk放入解壳程序的dex文件中。

解壳程序是最后替代我们apk安装到手机中运行的程序。它在执行中从自己的dex中释放出我们apk程序。

二、加壳作用

加壳的程序可以有效阻止对程序的反汇编分析,其实就是鱼目混珠。

参考链接:

http://www.cnblogs.com/cute/p/4809386.html

评论
你好,访客