Android APK 签名校验

admin 2024年7月4日17:23:02评论3 views字数 2271阅读7分34秒阅读模式

对称加密算法

非对称加密算法需要两个密钥:公开密钥(简称公钥)和私有密钥(简称私钥)。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密;如果用私钥对数据进行加密,那么只有用对应的公钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。非对称加密算法是数字签名和数字证书的基础,大家非常熟悉的RSA就是非对称加密算法的一种实现。

消息摘要算法

消息摘要算法(Message Digest Algorithm)是一种能产生特殊输出格式的算法,其原理是根据一定的运算规则对原始数据进行某种形式的信息提取,被提取出的信息就被称作原始数据的消息摘要。著名的摘要算法有RSA公司的MD5算法和SHA-1算法及其大量的变体。

数字证书一般包含

1.证书发布机构

2.证书的有效期

3.消息发送方的公钥

4.证书的所有者

5.数字签名所使用的算法

6.数字签名

APK签名前的包结构

Android APK 签名校验

APK签名后的包结构

Android APK 签名校验

META-INF文件夹内容

Android APK 签名校验

其实,在Android的源代码里包含了一个工具,可以对apk文件进行签名,具体的代码位置在buildtoolssignapk目录下,通过分析其中的SignApk.Java文件,可以大致了解签名的过程。其流程大致有如下几步:

1)打开待签名的apk文件(由于apk其实是一个用zip压缩的文件,其实就是用zip解压整个apk文件),逐一遍历里面的所有条目,如果是目录就跳过,如果是一个文件,就用SHA1(或者SHA256)消息摘要算法提取出该文件的摘要然后进行BASE64编码后,作为“SHA1-Digest”属性的值写入到MANIFEST.MF文件中的一个块中。该块有一个“Name”属性,其值就是该文件在apk包中的路径。

Android APK 签名校验

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

Android APK 签名校验

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

Android APK 签名校验

3)把之前生成的 CERT.SF文件, 用私钥计算出签名, 然后将签名以及包含公钥信息的数字证书一同写入 CERT.RSA 中保存。CERT.RSA是一个满足PKCS7格式的文件,可以通过openssl工具来查看签名证书的信息。在Ubuntu或者在Windows上使用Cygwin,敲入以下命令:

[plain] view plain copy

openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs –text

可以得到如下输出:

Android APK 签名校验

校验apk文件被篡改

首先,如果你改变了apk包中的任何文件,那么在apk安装校验时,改变后的文件摘要信息与MANIFEST.MF的检验信息不同,于是验证失败,程序就不能成功安装。

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

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

那么能不能继续伪造数字签名呢?不可能,因为没有数字证书对应的私钥。

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

假设签名后,apk文件中多了一个META-INF目录,里面有三个文件,分别是MANIFEST.MFCERT.SFCERT.RSA

Android APK 签名校验

目前知道,MANIFEST.MF中记录的是apk中所有文件的摘要值;CERT.SF中记录的是对MANIFEST.MF的摘要值,包括整个文件的摘要,还有文件中每一项的摘要;而CERT.RSA中记录的是对CERT.SF文件的签名,以及签名的公钥。

Android平台上所有应用程序安装都是由PackageManangerService(代码位于frameworksbaseservicescorejavacomandroidserverpmPackageManagerService.java)来管理的,Android的安装流程非常复杂,与签名验证相关的步骤位于installPackageLI函数中。

总结

1)Android应用程序签名只是用来解决发布的应用不被别人篡改的,其并不会对应用程序本身进行加密,这点不同于Windows Phone和iOS。

2)Android并不要求所有应用程序的签名证书都由可信任CA的根证书签名,通过这点保证了其生态系统的开放性,所有人都可以用自己生成的证书对应用程序签名。

3)如果想修改一个已经发布的应用程序,哪怕是修改一张图片,都必须对其进行重新签名。但是,签原始应用的私钥一般是拿不到的(肯定在原始应用程序开发者的手上,且不可能公布出去),所以只能用另外一组公私钥对,生成一个新的证书,对重打包的应用进行签名。所以重打包的apk中所带证书的公钥肯定和原始应用不一样。同时,在手机上如果想安装一个应用程序,应用程序安装器会先检查相同包名的应用是否已经被安装过,如果已经安装过,会继续判断已经安装的应用和将要安装的应用,其所携带的数字证书中的公钥是否一致。如果相同,则安装;而如果不同,则会提示用户先卸载。

原文始发于微信公众号(R0LL):Android APK 签名校验

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年7月4日17:23:02
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Android APK 签名校验https://cn-sec.com/archives/2919801.html

发表评论

匿名网友 填写信息