跨平台应用开发进阶(二十二) :Android 应用安全机制实现方案_android 安全软件开发

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 使用说明
  1. 解压下载包
  2. 命令行执行(需要jdk环境)
 java -jar ApkSigner.jar [-appname test] -keystore keystorePath -alias alias [-pswd password] [-aliaspswd aliasPassword] apkPath(or directory)

注意⚠️:签名之后,如果需要进行对齐操作,请调用命令: zipalign -f 4 in.apk out.apkzipalign 这个程序在 android sdk 有提供。

(可选)android7.0及之后的apk,可以采用v2签名,提高apk安装速度。但是为了兼容android7.0之前的系统,也需要进行v1签名,且需要先进行v1签名,apk字节对齐(可选),再进行v2签名。具体步骤命令如下:

  1. java -jar ApkSigner.jar [-appname test] -keystore keystorePath -alias alias [-pswd password] [-aliaspswd aliasPassword] -v1 true -v2 false in.apk
  2. zipalign -c -f [alignmentSize] in.apk out.apk (可选)
  3. java -jar ApkSigner.jar [-appname test] -keystore keystorePath -alias alias [-pswd password] [-aliaspswd aliasPassword] -v1 false -v2 true out.apk

其中,option参数说明:

  • appname 待签名的应用程序名,可选,但建议不同的APP填上对应的app名(可以为中文),有助于【加速】;
  • keystore 后跟.keystore签名文件;
  • alias 后跟签名别名;
  • pswd 后跟对应签名的密码,例如这里是:android 可选,如果不填,则签名的时候需要手动输入;
  • aliaspswd 对应别名 alias 的密码,如果没有则默认使用 keystorePassword,最后跟待签名的APK路径或者目录路径 ,如果跟的是目录则是批量签名;
  • v1 true(默认)表示使用v1签名模式,false表示不使用;
  • v2 true表示使用v2签名模式,false(默认)表示不适用;
3.4 V1、V2、V3、V4签名方案

Android 目前支持以下四种应用签名方案:

  • v1 方案:基于 JAR 签名。
  • v2 方案:APK 签名方案 v2(在 Android 7.0 中引入)
  • v3 方案:APK 签名方案 v3(在 Android 9 中引入)
  • v4 方案:APK 签名方案 v4(在 Android 11 中引入)

其中,v1 到 v2 是颠覆性的,为了解决 JAR 签名方案的安全性问题,而到了 v3 方案,其实结构上并没有太大的调整,可以理解为 v2 签名方案的升级版,有一些资料也把它称之为 v2+ 方案。

3.4.1 v1 签名

Android 7.0 (即 Android N,Android Api 24) 以下的版本,只能使用旧签名方案,也就是 v1 签名。

v1 签名使用 JDKjarsigner 工具,对 zip 压缩包的每个文件进行验证,签名后仍可对压缩包进行修改、移动、重新压缩文件。

V1 签名的机制主要就在 META-INF 目录下的三个文件,MANIFEST.MFCERT.SFCERT.RSA,他们都是 V1 签名的产物。

在 V1 签名方案中,并不会保护 APK 内的所有文件,会存在一些例外部分,即便被修改也不会导致签名失效。

例如:ZIP 元数据。同时,v1 方案对 APK 内部被保护的原始文件,是单独进行计算数据摘要的,所以在验证时,需要先解压再验证,导致安装时会花费更多的时间消耗更多的内存。例如 v1 方案中签渠道的方式就是利用了此特性,将渠道信息写入 META-INF 文件中,这不会破坏 v1 签名。

在这里插入图片描述

缺点:不安全、速度慢

为了解决这些问题,Android 7.0 中引入了 APK 签名方案 v2。

3.4.2 v2 签名

Android 7.0 开始,Google 新增了 v2 签名方案。

v2 签名使用 Google 自带的 apksigner 工具,对 zip 压缩包的整个文件进行验证,签名后不能修改压缩包,包括 zipalgin

如果你对 v2 签名的 apk 解压,没有发现签名文件,重新压缩后 v2 签名失效,这说明 v2 签名是对整个 Apk 进行签名验证。

v2 签名是一种全文件签名方案,该方案能够发现对 APK 的受保护部分进行的所有更改,从而有助于加快验证速度并增强完整性保证

使用 APK 签名方案 v2 进行签名时,会在 APK 文件中插入一个 APK 签名分块,该分块位于「ZIP 中央目录」部分之前并紧邻该部分。在「APK 签名分块」内,v2 签名和签名者身份信息会存储在 APK 签名方案 v2 分块中。

在这里插入图片描述

上图是签名前后,APK 文件结构的对比。可以看到在 v2 已签名的 APK 中,包含了 4 个部分:

  • ZIP 条目的内容
  • APK 签名分块(APK Signing Block)
  • ZIP 中央目录
  • ZIP 中央目录结尾

在验证期间,v2+ 方案会将 APK 文件视为 blob,并对整个文件进行签名检查。对 APK 进行的任何修改(包括对 ZIP 元数据进行的修改)都会使 APK 签名作废。这种形式的 APK 验证不仅速度要快得多,而且能够发现更多种未经授权的修改。

新的签名格式向后兼容,因此,使用这种新格式签名的 APK 可在更低版本的 Android 设备上进行安装(会直接忽略添加到 APK 的额外数据),但前提是这些 APK 还带有 v1 签名。

在这里插入图片描述
从安全的角度 v2 会比 v1 更安全,v2 签名是验证整个打包后的 APK 文件,所以对其 APK 文件做「任何」改动都会破坏签名。注意这里的任何是带引号的,V2签名的签名块其实是一个 K-V 的结构,可以向其中插入一些简单的数据而不破坏 v2 签名,这就是 v2 方案下,多渠道的方案思路。

缺点是:无法解决签名过期更换签名的问题

3.4.3 v2 签名相对 v1 签名的优点
  • 因为不能修改压缩包,所以 v2 签名会更安全。
  • v2 签名是对整个 Apk 进行签名验证,不需要解压验证,所以签名验证的时间会更短。
3.4.4 v3 签名

v2 方案解决了安全问题以及安装时验证的效率问题,但是它并没有解决更换签名问题

Android 9.0 中引入了新的签名方式,它的格式大体和 v2 类似,在 v2 插入的签名块(Apk Signature Block v2)中,又添加了一个新快(Attr块)。

在这个新块中,会记录之前的签名信息以及新的签名信息,以密钥转轮的方案,来做签名的替换和升级。这意味着,只要旧签名证书在手,就可以通过它在新的 APK 文件中,更改签名。

在这里插入图片描述

V3 签名新增的新块(attr)存储了所有的签名信息,由更小的 Level 块,以链表的形式存储。

其中每个节点都包含用于为之前版本的应用签名的签名证书,最旧的签名证书对应根节点,系统会让每个节点中的证书为列表中下一个证书签名,从而为每个新密钥提供证据来证明它应该像旧密钥一样可信。

这个过程有点类似 CA 证书的证明过程,已安装的 App 的旧签名,确保覆盖安装的 APK 的新签名正确,将信任传递下去。

3.4.5 v4 签名

在传统的应用安装方案中,开发者通过 ADB(Android Debug Bridge)以有线或无线的方式与终端用户连接,或者用户从软件商店直接下载,然而该方案需要用户等待完整的安装包传输结束后才能启动安装,在这期间产生了不良的用户体验。

增量安装技术是一种流式安装方案:一旦安装包的核心文件传输完成便可启动应用。流式安装意味着允许优先传输核心数据以启动应用,并在后台流式传输剩余数据。

在Android 11中,Google在内核中实现了增量文件系统用于对增量安装的支持。

这使得 Android os 可以通过 ADB 流式传输 APK。同时,Android 11 为了适应增量安装,添加了新的 v4签名方案。

此方案不改变前代签名方案而是创建一种新的签名:基于 APK 所有字节数据计算出 Merkle 哈希树,并将Merkle 树的根哈希、盐值作为签名数据进行包完整性验证。新的签名数据保存在 .idsig 文件中并且在进行增量安装前必须为APK创建对应的 v4 签名文件。

官方文档:v4签名

3.4.6 总结
  • v1 签名实际上就是 JAR 签名的方案,它不会保护 APK 内的所有文件,存在安全和效率问题;
  • v2 签名是一种全文件签名方案,增加了 APK 签名块(APK Signing Block),但仍无法解决更换签名的问题;
  • v3 签名是 v2 的升级版,也被称为 v2+。在 V2 插入的签名块(Apk Signature Block V2)中,又添加了一个新快(Attr 块),它使用链表存储了所有的签名信息,验证时就像 CA 证书的证明过程。
  • v4 签名是为了增量安装技术而产生的一种新的签名方案。
3.4.7 小结

如果想无缝升级一个应用,Android系统要求应用程序的新版本与老版本具有相同的签名与包名。若包名相同而签名不同,系统会拒绝安装新版应用。

若APK签名策略由V1升级至V1+V2+V3,且升级前后的APP签名与包名保持一致,则可以做到无缝升级。

按照以下步骤实现APK签名、校验。

  1. apksigner签名(签名结果:V1+V2+V3
apksigner sign --ks android.jks --ks-key-alias android --out signed.apk unsigned.apk

  1. 查看签名文件
keytool -v -list -keystore xxx.jks

  1. 查看apk 签名
keytool -printcert -jarfile ./weixin806android1900_arm64.apk

  1. 签名策略校验
apksigner verify --verbose signed.apk

  1. 查看apk的基本配置信息(packageNameversionCode等info)
aapt dump badging test.apk

3.5 jarsigner 与 apksigner
3.5.1 jarsigner

jarsignerJDK 提供的针对 jar 包签名的工具,如果你本地已经安装了 Java 环境,会自带 jarsigner

比如我的 jarsigner 工具的位置在

/Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/bin/jarsigner

效果图如下:

在这里插入图片描述

3.5.2 apksigner

apksignerGoogle 官方提供的针对 Android Apk 签名和验证的专用工具,位于 Android SDK / build-tools / SDK 版本 / apksigner

以我本地的 Android SDK 30.0.2 版本为例, apksigner 工具的位置在
/Users/suxing/Library/Android/sdk/build-tools/30.0.2/apksigner

效果图如下:

在这里插入图片描述

如果你用的是 Android Studio 或者 IDEA ,安装这两个编辑器时会自动下载 Android SDK ,所以 apksigner 工具也不需要另外安装。

不过,无论是 apk 包还是 jar 包,其本质都是 zip 格式的压缩包,如果只针对 v1 签名的话,两者的签名过程其实差不多。

apksigner 工具默认同时使用 v1v2 签名,以兼容 Android 7 以下的系统版本。

为方便应用apksigner签名,可将apksigner径配置到系统环境变量path。实现步骤如下:

  1. cd ~
  2. open -e .bash_profile
  3. source .bash_profile

.bash_profile文件内容如下:

source ~/.bashrc

# Git branch in prompt.

parse\_git\_branch() {

    git branch 2> /dev/null | sed -e '/^[^\*]/d' -e 's/\* \(.\*\)/ (\1)/'

}

export PS1="\u@\h \W\[\033[32m\]\$(parse\_git\_branch)\[\033[00m\] $ " 

source ~/.bashrc

export ANDROID\_HOME=/Users/ccms-m-03/Library/Android/sdk
export PATH=${PATH}:${ANDROID\_HOME}/tools
export PATH=${PATH}:${ANDROID\_HOME}/platform-tools

export AAPT\_HOME=/Users/ccms-m-03/Library/Android/sdk/build-tools/30.0.3
export PATH=$PATH:$AAPT\_HOME

source ~/.bashrc

apksigner通过以下指令实现apk签名。

apksigner sign --ks android.jks --ks-key-alias android --out signed.apk unsigned.apk

  • --ks .jks文件路劲
  • --ks-key-alias 签名文件别名
  • --out 输出签名后的目标路径
  • unsigned.apk 未签名的原始apk文件路径

为了避免路径过长,书写错误的、问题,建议将加固包jks文件放置在同一目录。

在这里插入图片描述

其实从文件的大小我们就可以看到有变化,但是还得验证是否签名成功,用以下指令校验:

 apksigner verify --verbose signed.apk

签名成功如下图:

在这里插入图片描述

没有签名如下提示:

在这里插入图片描述

签名后如果包能正确安装到手机(无需运行)则没有问题,如果安装失败请用命令安装:adb install apkfile 查看出错信息。

注⚠️:通过apksigner可视化工具签名后的签名方案为V1,用apksigner sign --ks android.jks --ks-key-alias android --out signed.apk unsigned.apk命令行签名后的签名方案为V1+V2+V3!

3.5.3 查看 Android 和 iOS 打包时间
3.5.3.1 查看 Android .apk 打包时间

解压后可查看META-INF.RSA.SF.MF等文件的日期就是打包日期。

在这里插入图片描述

3.5.3.2 查看 iOS .ipa 打包时间

ios 可以查看 info.plist 文件的时间。
在这里插入图片描述

3.5.4 签名文件 jks 与 keystore 格式
  • .jks是在android studio里面生成的签名证书。
  • .keystoreeclipse里面生成的签名证书。

两者在使用方式上没有什么区别,但是在算法上有一点区别。

3.5.4.1 jks 转 keystore

在应用apksigner 可视化签名工具进行APK签名时,发现只支持.keystore格式的签名文件,需要把.jks签名格式转化为.keystore格式。

直接用命令行转换,先生成.p12文件,用.p12生成.keystore

keytool -importkeystore -srckeystore test.jks -srcstoretype JKS -deststoretype PKCS12 -destkeystore test.p12

keytool -v -importkeystore -srckeystore test.p12 -srcstoretype PKCS12 -destkeystore test.keystore -deststoretype JKS

转换后,会看到如下提示信息。可以通过提示的命令行

keytool -importkeystore -srckeystore cicc-keystore.keystore -destkeystore cicc-keystore.keystore deststoretype pkcs12

按照指定行业标准格式进行转换。

Warning: JKS 密钥库使用专用格式。建议使用 “keytool -importkeystore -srckeystore
cicc-keystore.keystore -destkeystore cicc-keystore.keystore
-deststoretype pkcs12” 迁移到行业标准格式 PKCS12。

现在test.keystore的签名应该与test.jks的签名信息是一样的了。

可以通过以下命令来验证:

keytool -v -list -keystore test.keystore

3.5.4.2 keystore 转 jks

同理,.keystore也可以转.jks,转换命令如下:

keytool -importkeystore -srckeystore test.keystore -srcstoretype JKS -deststoretype PKCS12 -destkeystore test.p12

keytool -v -importkeystore -srckeystore test.p12 -srcstoretype PKCS12 -destkeystore test.jks -deststoretype JKS

3.6 签名验证

应用签名工具对APP做好签名后,如何验证签名的正确性,或者是给你一个apk,如何验证该apk是否完成了签名操作。

3.6.1 查看apk 签名

应用 keytool 工具可实现文件签名验证。

keytool -printcert -jarfile ./weixin806android1900_arm64.apk 

apk为已签名,则会显示以下信息:

在这里插入图片描述

apk未签名,则会提示不是已签名的 jar 文件

拓展阅读KeyTool是Java中的数字证书管理工具,用于数字证书的申请、导入、导出和撤销等证书管理操作,位于<JAVA_HOME>\bin\keytool.exe。要获得数字证书需要使用数字证书管理工具(如KeyToolOpenSSL)构建CSR(Certificate Signing Request数字证书签发申请),交由CA机构签发,形成最终的数字证书。

3.6.2 查看签名文件

同样使用 keytool 工具查看 xxx.keystore 或者 xxx.jks,注意查看自己的签名文件则需要密码输入才能查看。根据以下命令输出信息,通过对比apk签名输出的MD5sha信息是否一致,一致则代表签名成功。

keytool -v -list -keystore xxx.jks 

四、APP 信息校验

APP组好包之后,如何查看包信息?

4.1 APK 信息查看

首先找到aapt工具,在Android SDK文件夹下的build-tools包里应用aapt命令便可实现查看Android APK信息。

或者将aapt命令添加到环境变量。

然后,通过aapt命令便可查看apk包的packageName、versionCode、applicationLabel、launcherActivity、permission等各种详细信息

先 cd 到 apk 所在目录,然后执行以下命令 :

查看apk的基本配置信息

aapt dump badging test.apk

在这里插入图片描述

查看apk的权限

读者福利

========

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

由于篇幅过长,就不展示所有面试题了,想要完整面试题目的朋友(另有小编自己整理的2024大厂高频面试题及答案附赠)


  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值