MANIFEST.MF
为摘要文件。
MANIFEST.MF
中保存了APK里所有文件的SHA1校验值的BASE64编码,程序遍历Apk包中的所有文件(entry),对非文件夹非签名文件的文件,逐个用SHA1生成摘要信息,再用Base64进行编码,格式如下(一个文件对应一条记录):
Name: res/anim/abc_fade_in.xml
SHA1-Digest: ohPEA4mboaFUu9LZMUwk7FmjbPI=
Name: res/anim/abc_fade_out.xml
SHA1-Digest: MTJWZc22b5LNeBboqBhxcQh5xHQ=
如果你改变了apk包中的文件,那么在apk安装校验时,改变后的文件摘要信息与MANIFEST.MF
的检验信息不同,于是程序就不能成功安装。
如果攻击者修改了程序的内容,又重新生成了新的摘要,那么就不可以通过验证,所以这是一个非常简单的验证。
3.2.2 CERT.SF
CERT.SF
是对摘要的签名文件。
SF文件里保存了MANIFEST.MF
文件的SHA1校验值的BASE64编码,同时还保存了MANIFEST.MF
中每一条记录的SHA1检验值BASE64编码,格式如下:
SHA1-Digest-Manifest: ZRhh1HuaoEKMn6o21W1as0sMlaU=
Name: res/anim/abc_fade_in.xml
SHA1-Digest: wE1QEZhFkLBWMw4TRtxPdsiMRtA=
Name: res/anim/abc_fade_out.xml
SHA1-Digest: MfCV1efdxSKtesRMF81I08Zyvvo=
对前一步生成的MANIFEST.MF
,使用SHA1-RSA
算法,用开发者的私钥进行签名。在安装时只能使用公钥才能解密它。解密之后,将它与未加密的摘要信息(即,MANIFEST.MF
文件)进行对比,如果相符,则表明内容没有被异常修改。
在这一步,即使开发者修改了程序内容,并生成了新的摘要文件,但是攻击者没有开发者的私钥,所以不能生成正确的签名文件(CERT.SF
)。系统在对程序进行验证的时候,用开发者公钥对不正确的签名文件进行解密,得到的结果和摘要文件(MANIFEST.MF
)对应不起来,所以不能通过检验,不能成功安装文件。
3.2.3 CERT.RSA
CERT.RSA
文件是一个X.509
格式证书。
.RSA
文件还可能是.DSA
文件,RSA与SF文件的文件名可以更改,但是它们的命名必须一样。
RSA文件则包含了签名公钥、签名所有者等信息,还保存了用SHA1withRSA
签名算法对CERT.SF
文件的签名结果信息。
使用 openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs -text
命令查看证书CERT.RSA
内容:
由上图可知,在CERT.RSA
文件中有两个签名信息,一个是证书的签名信息,另一个是证书附加信息中CERT.SF
的签名信息。
系统对CERT.SF
文件进行签名校验,所需要的公钥就是从证书里取出来的,由于证书中包含了证书签名信息,我们可以在代码中预埋证书签名信息,校验证书中的签名是否一致,防止第三方使用他的私钥重新签名apk。
证书自身的签名信息可以用于校验apk是否被第三方重新打包,当第三方使用自己的私钥签名apk时,其生成的证书的签名值与我们生成的证书签名值不同,因此可以在此处进行校验。
附加信息中的CERT.SF
的签名信息在apk安装时,安装器会重新CERT.SF
的签名内容与附加信息中的CERT.SF
的签名信息进行对比判断apk是否被篡改。
通常我们所说的签名是指证书的签名信息。
Android系统就是根据这三个文件的内容对APK文件进行签名检验的。
为什么要签名呢?是不是最安全的呢?如果apk文件被篡改后会发生什么?
首先,如果你改变了apk包中的任何文件,那么在apk安装校验时,改变后的文件摘要信息与MANIFEST.MF
的检验信息不同,于是验证失败,程序就不能成功安装。
其次,如果你对更改的过的文件相应的算出新的摘要值,然后更改MANIFEST.MF
文件里面对应的属性值,那么必定与CERT.SF
文件中算出的摘要值不一样,照样验证失败。
最后,如果你还不死心,继续计算MANIFEST.MF
的摘要值,相应的更改CERT.SF
里面的值,那么数字签名值必定与CERT.RSA
文件中记录的不一样,还是失败。
那么能不能继续伪造数字签名呢?不可能,因为没有数字证书对应的私钥。
所以,如果要重新打包后的应用程序能再Android设备上安装,必须对其进行重签名。
结论:只要修改了Apk中的任何内容,就必须重新签名,否则会提示安装失败!
签名的话,一般使用通用签名工具ApkSigner
。
ApkSigner
是jar包形式的签名工具,较传统工具签名快很多,适用于Win/Mac/Linux
环境。
3.3 使用说明
- 解压下载包
- 命令行执行(需要
jdk
环境)
java -jar ApkSigner.jar [-appname test] -keystore keystorePath -alias alias [-pswd password] [-aliaspswd aliasPassword] apkPath(or directory)
注意⚠️:签名之后,如果需要进行对齐操作,请调用命令: zipalign -f 4 in.apk out.apk
, zipalign
这个程序在 android sdk
有提供。
(可选)android7.0
及之后的apk,可以采用v2
签名,提高apk
安装速度。但是为了兼容