Android10.0应用安装白名单---添加签名校验

2024-05-15 06:58

本文主要是介绍Android10.0应用安装白名单---添加签名校验,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景

为了避免系统被安装上各种各样的app,客户要求系统需要有个安装白名单的功能。

文章目录

  • 背景
  • 思路
  • Android应用签名
  • apk安装白名单进行签名校验
    • 获取apk签名的证书指纹
    • android源码中获取证书指纹
    • 签名校验
  • 结语
  • 微信公众号

思路

白名单功能主要是通过确认要安装的应用是否在白名单上,如果不在,则不允许安装。筛选的标准可以通过包名进行判断。但单纯包名进行判断还是不够安全,这里是想再加个签名校验的机制,毕竟每个签名都是独一无二的。

这个过程,主要难点在于如何获取各个apk签名。在说明如何在代码中获取到系统签名之前,先大概说下Android应用的签名机制。

Android应用签名

签名的基本目的就是不允许apk内部任意一个文件的内容被篡改。所以得保证每个文件都被加密到。
将任意一个签过名的apk进行解压,都可以发现一个叫META-INF的文件夹,该文件夹包括但不限于如下三个文件:

CERT.RSA CERT.SF MANIFEST.MF

1.MANIFEST.MF文件。对APK包中每个文件(文件夹和签名文件除外)进行遍历,使用SHA1或者SHA256生成摘要信息。然后再用base64进行编码,截取MANIFEST.MF文件中某一段:

Name: AndroidManifest.xml
SHA1-Digest: D2yOY7wstlBC3AbjQznUDa6/8Xw=

这里我们可以自己对AndroidManifest.xml这个文件通过SHA1生成摘要信息,有在线的SHA1:

http://www.metools.info/code/c92.html

在这里插入图片描述

拿到摘要后,可以通过在线base64编码,将此摘要进行编码:

http://tomeko.net/online_tools/hex_to_base64.php?lang=en

在这里插入图片描述

可以看到这里获取到的base64编码结果跟MANIFEST.MF文件描述的一样。

其余文件的base64编码也是如此计算得来。从这里就知道,如果apk中的文件被篡改了,则最终得到的base64编码跟MANIFEST.MF文件描述不一样,就会导致安装出错。当然,也可以手动计算出所修改文件的base64编码,然后更新到MANIFEST.MF文件中,但也会功亏一篑,因为还有CERT.RSA和CERT.SF。

2.CERT.SF文件。截取部分该文件:

Signature-Version: 1.0
SHA1-Digest-Manifest: iaeBE2KJWElTbmMNGnjxretMvz8=
Created-By: 1.0 (Android SignApk)Name: kotlin/collections/MapWithDefault.kotlin_metadata
SHA1-Digest: je8WuIzQjM5yX2bkDmjjyviMxOE=Name: kotlin/coroutines/intrinsics/CoroutinesIntrinsicsHKt.kotlin_metadata
SHA1-Digest: reRpbwjfyR7tladgIdLzjpREduA=Name: res/interpolator/btn_checkbox_checked_mtrl_animation_interpolator_0.xml
SHA1-Digest: 9Lo7vzAcNsmM/qCg9/iamygexzk=

这个文件是对MANIFEST.MF文件中的每一项再做一次SHA1计算,然后再进行base64编码。另外还对MANIFEST.MF文件的内容进行SHA1计算,然后进行编码,将该值写到SHA1-Digest-Manifest中:

SHA1-Digest-Manifest: iaeBE2KJWElTbmMNGnjxretMvz8=

这里对MANIFEST.MF文件进行了一层篡改保护,只要MANIFEST.MF文件被修改过,那最后得到的base64编码肯定对不上。当然,到此为止,如果只是做到这一步,那还是可以被篡改的。关键看看CERT.RSA文件。

3.CERT.RSA文件。该文件保存了公钥,所采用的加密算法等信息。还有比较重要的是,对CERT.SF文件的内容用私钥进行加密之后的值。也就是说,即使手动篡改了MANIFEST.MF文件和CERT.SF文件,CERT.RSA文件还是会对应不上,安装就会失败。

apk安装白名单进行签名校验

上面所说是签名的过程,而安装则是反过来。

CERT.RSA这个文件中的包含的公钥对数字签名(自己本身)进行解密,将解密后的结果与CERT.SF文件hash运算后的结果进行比对,一致的话就返回证书链信息,并将证书链保存在certificates对象中,同时说明CERT.SF文件没有被篡改。如果这里对比通过,则下一步就验证MANIFEST.MF是否被篡改。在这一步,会遍历每个文件(entry),对非文件夹非签名文件的文件,逐个生成SHA1的数字签名信息,再用Base64进行编码,并与MANIFEST.MF中对内容进行比对,若一一对应,则表示文件没被篡改。到这里校验APK所有文件是否有被篡改,也已完成。

显然,如果我们想要在安装白名单上实现签名校验,那可以对比RSA文件上的证书签名是否与apk的签名一致即可。

获取apk签名的证书指纹

拿到app后,通过解压apk,获取到CERT.RSA文件,执行如下指令:

keytool -printcert -file CERT.RSA

会可以得到签名的证书指纹:

Certificate fingerprints:MD5:  0E:BA:50:A4:5C:15:B3:5D:97:7D:04:D8:43:79:B3:58SHA1: 41:79:1C:9B:8F:AF:15:E1:AC:D5:AA:F5:92:10:FD:42:46:7D:82:70SHA256: 2D:37:0C:21:F5:DF:D5:53:D2:A7:96:31:4B:70:92:5F:B3:8A:DE:EF:90:86:4C:92:0B:BB:BB:12:88:7D:35:20

每个签名的证书指纹都是唯一的,如此一来,就可以通过该证书指纹的唯一性来进行签名校验了。

android源码中获取证书指纹

要想获取apk的签名证书指纹,就需要先获取其签名。app安装时通过PackageParser类来解析安装包的信息,而签名也包含其中。我们可以利用这个来获取到签名的证书指纹。具体的安装流程这里不多介绍,直接定位到PackageManagerService类的preparePackageLI方法,该方法会去new出一个PackageParser对象来做apk包的解析:

private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)throws PrepareFailure {...PackageParser pp = new PackageParser();pp.setSeparateProcesses(mSeparateProcesses);pp.setDisplayMetrics(mMetrics);pp.setCallback(mPackageParserCallback);Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");final PackageParser.Package pkg;try {pkg = pp.parsePackage(tmpPackageFile, parseFlags);DexMetadataHelper.validatePackageDexMetadata(pkg);} catch (PackageParserException e) {throw new PrepareFailure("Failed parse during installPackageLI", e);} finally {Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);}...try {// either use what we've been given or parse directly from the APKif (args.signingDetails != PackageParser.SigningDetails.UNKNOWN) {pkg.setSigningDetails(args.signingDetails);} else {PackageParser.collectCertificates(pkg, false /* skipVerify */);}} catch (PackageParserException e) {throw new PrepareFailure("Failed collect during installPackageLI", e);}...
}

这里列出部分代码,pkg是一个Pakage对象,属于PackageParser内部类,该类用于保存apk相关的信息,如包名,apk路径,签名等。

签名拿到后,就可以拿到它的证书指纹了,如下:

String sha1 = getFingerprint(pkg.mSigningDetails.signatures[0], "SHA1");private String getFingerprint(Signature signature, String hashAlgorithm) {if (signature == null) {return null;}try {MessageDigest digest = MessageDigest.getInstance(hashAlgorithm);return toHexadecimalString(digest.digest(signature.toByteArray()));} catch(NoSuchAlgorithmException e) {// ignore}return null;
}

MessageDigest 类为应用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。信息摘要是安全的单向哈希函数,它接收任意大小的数据,并输出固定长度的哈希值。
这里是根据SHA算法获取摘要,即证书指纹。

签名校验

用该指纹和使用keytool得出的SHA1值进行比对,如果符合,则签名校验通过,允许应用安装。具体实现也比较单,可以将keytool得出的SHA1值保存到白名单中,然后在apk安装过程中,再读出进行比对即可。

结语

每个签名的证书指纹,即消息摘要,是哪些内容经过SHA1、MD5、SHA256算法得到的呢?私钥加上其他的一些内容?

微信公众号

我在微信公众号也有写文章,更新比较及时,有兴趣者可以微信搜索【Android系统实战开发】,关注有惊喜哦!

这篇关于Android10.0应用安装白名单---添加签名校验的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/991126

相关文章

最详细安装 PostgreSQL方法及常见问题解决

《最详细安装PostgreSQL方法及常见问题解决》:本文主要介绍最详细安装PostgreSQL方法及常见问题解决,介绍了在Windows系统上安装PostgreSQL及Linux系统上安装Po... 目录一、在 Windows 系统上安装 PostgreSQL1. 下载 PostgreSQL 安装包2.

Maven如何手动安装依赖到本地仓库

《Maven如何手动安装依赖到本地仓库》:本文主要介绍Maven如何手动安装依赖到本地仓库问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、下载依赖二、安装 JAR 文件到本地仓库三、验证安装四、在项目中使用该依赖1、注意事项2、额外提示总结一、下载依赖登

Java中的Lambda表达式及其应用小结

《Java中的Lambda表达式及其应用小结》Java中的Lambda表达式是一项极具创新性的特性,它使得Java代码更加简洁和高效,尤其是在集合操作和并行处理方面,:本文主要介绍Java中的La... 目录前言1. 什么是Lambda表达式?2. Lambda表达式的基本语法例子1:最简单的Lambda表

Python结合PyWebView库打造跨平台桌面应用

《Python结合PyWebView库打造跨平台桌面应用》随着Web技术的发展,将HTML/CSS/JavaScript与Python结合构建桌面应用成为可能,本文将系统讲解如何使用PyWebView... 目录一、技术原理与优势分析1.1 架构原理1.2 核心优势二、开发环境搭建2.1 安装依赖2.2 验

Java使用ANTLR4对Lua脚本语法校验详解

《Java使用ANTLR4对Lua脚本语法校验详解》ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件,下面就跟随小编一起看看Java如何使用ANTLR4对Lua脚本... 目录什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Gramm

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

如何在Mac上安装并配置JDK环境变量详细步骤

《如何在Mac上安装并配置JDK环境变量详细步骤》:本文主要介绍如何在Mac上安装并配置JDK环境变量详细步骤,包括下载JDK、安装JDK、配置环境变量、验证JDK配置以及可选地设置PowerSh... 目录步骤 1:下载JDK步骤 2:安装JDK步骤 3:配置环境变量1. 编辑~/.zshrc(对于zsh

SpringShell命令行之交互式Shell应用开发方式

《SpringShell命令行之交互式Shell应用开发方式》本文将深入探讨SpringShell的核心特性、实现方式及应用场景,帮助开发者掌握这一强大工具,具有很好的参考价值,希望对大家有所帮助,如... 目录引言一、Spring Shell概述二、创建命令类三、命令参数处理四、命令分组与帮助系统五、自定

SpringBoot应用中出现的Full GC问题的场景与解决

《SpringBoot应用中出现的FullGC问题的场景与解决》这篇文章主要为大家详细介绍了SpringBoot应用中出现的FullGC问题的场景与解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录Full GC的原理与触发条件原理触发条件对Spring Boot应用的影响示例代码优化建议结论F

SpringValidation数据校验之约束注解与分组校验方式

《SpringValidation数据校验之约束注解与分组校验方式》本文将深入探讨SpringValidation的核心功能,帮助开发者掌握约束注解的使用技巧和分组校验的高级应用,从而构建更加健壮和可... 目录引言一、Spring Validation基础架构1.1 jsR-380标准与Spring整合1