背景
最近在调研一个测试工具的使用,在使用中发现被测试工具处理过的apk文件经安装后打开就会崩溃,分析崩溃日志后原因是签名不一致导致的。
说到Android中的签名,可能大家都知道签名的目的就是为了保护apk文件的安全,如果apk被恶意篡改后经过安装校验的时候,就会出现校验失败,导致安装包安装失败的情况。但如果更深去问一下Android签名机制和原理,是不是就被问住了?接下来的就让我们去探究Android签名机制和原理。
Android 签名机制和原理
Android系统在安装APK的时候,首先会检验APK的签名,如果发现签名文件不存在或者校验签名失败,则会拒绝安装,所以应用程序在发布之前一定要进行签名。给APK签名可以带来以下好处:
应用程序升级如果想无缝升级一个应用,Android系统要求应用程序的新版本与老版本具有相同的签名与包名。若包名相同而签名不同,系统会拒绝安装新版应用。
应用程序模块化Android系统可以允许同一个证书签名的多个应用程序在一个进程里运行,系统实际把他们作为一个单个的应用程序。此时就可以把我们的应用程序以模块的方式进行部署,而用户可以独立的升级其中的一个模块。
代码或数据共享Android提供了基于签名的权限机制,一个应用程序可以为另一个以相同证书签名的应用程序公开自己的功能与数据,同时其它具有不同签名的应用程序不可访问相应的功能与数据。
应用程序的可认定性签名信息中包含有开发者信息,在一定程度上可以防止应用被伪造。例如网易云加密对Android APK加壳保护中使用的“校验签名(防二次打包)”功能就是利用了这一点。
签名的目的:
1. 对发送者的身份认证:
由于开发商可能通过使用相同的package name来混淆替换已经安装的程序,以此保证签名不同的包不被替换。
2. 保证信息传输的完成性:
签名对于包中的每个文件进行处理,以此确保包中内容不被替换。
3. 防止交易中的抵赖发生,market对软件的要求。
签名原理:
简单来说总体分为以下几个步骤:
1. 对Apk中的每个文件做一次算法(数据摘要+Base64编码),保存到MAINFEST.MF
2. 对MAINFEST.MF整个文件做一次算法(数据摘要+B阿瑟64编码),存放到CERT.SF文件的头属性中,在对MAINFEST.MF文件中各个属性块做一次算法(数据摘要+Base64编码),存放到一个属性块中。
3. 对CERT.SF文件做签名,内容存档到CERT.RSA中
对一个APK文件签名之后,APK文件根目录下会增加META-INF目录,该目录下增加三个文件,分别是:MANIFEST.MF、CERT.SF和CERT.RSA,以下是具体的流程:
MANIFEST.MF
这是摘要文件,文件中保存了APK里面所有文件的SHA1校验值的BASE64编码,格式如下(一个文件对应一条记录)。如果改变了APK包中的文件,在apk安装校验时,改变后的文件摘要信息与 MANIFEST.MF 的检验信息不同,程序就不会安装成功。假如攻击者修改了程序的内容,又重新生成了新的摘要,就可以通过验证。
Name: AndroidMainfest.xmlSHA1-Digest: incCj47jcu56R8pKV8dLACZBKD8=Name: META-INF/android.arch.core_runtime.versionSHA1-Digest: BeF7ZGqBckDCBhhvlPj0xwl01dw=
CERT.SF
这是对摘要的签名文件,对前一步生成的MANIFEST.MF,使用SHA1-RSA算法,用开发者的私钥进行签名。在安装时只能使用公钥才能进行解密。解密之后,与未加密的MANIFEST.MF进行对比,如果相符,则表明内容没有被异常修改。如果在这一步,开发者修改了程序内容,并生成了新的摘要文件,但是攻击者没有开发者的私钥,所以不能生成正确的签名文件。系统在对程序进行验证的时候,用开发者公钥对不正确的签名文件进行解密,得到的结果和摘要文件对应不起来,导致不能通过检验,不能成功安装文件。文件格式如下:
Name: AndroidMainfest.xmlSHA1-Digest: SyFsd2VUpCg4nq8jSOB7dBwuMyI=Name: META-INF/android.arch.core_runtime.versionSHA1-Digest: OPQCkzMXJVPQryHeMowVNZmfRMw=
CERT.RSA
该文件中保存了公钥、所采用的加密算法等信息。
从上面的内容来看,Android系统就是根据这三个文件的内容对APK文件进行签名检验的。