公司动态
androd签名apk笔记
Android 应用签名机制 知识思维导图覆盖了 7 大主题分支为什么App需要系统签名 — 身份认证、完整性防篡改、升级管控、数据共享、系统级权限网上下载的App能安装的原因 — 未知来源权限、签名有效性、绕过纯净模式、APK完整性如何判断APK是否可信 — 权限检查、签名验证、多引擎扫描、官方渠道下载开发者如何给应用签名 — 生成证书→签名→Zipalign→验证系统签名是否需要源码 — 源码编译方式、手动提取密钥重签名、安装限制权限授权流程 — Shared User ID声明、特权白名单配置、敏感运行时权限处理签名版本演进 (v1/v2/v3) — 各版本保护范围与兼容性对比讲讲开发者是怎么给应用签名的开发者给应用签名的过程实际上是一个从“生成身份证书”到“验证并优化安装包”的标准化流程。通常可以分为以下四个核心步骤第一步生成数字证书密钥库开发者首先需要创建一个包含私钥的数字证书通常以 .keystore 或 .jks 为后缀。这一步相当于开发者为自己打造一枚“专属印章”。在实际操作中开发者会使用 Java 开发工具包JDK中的 keytool 工具通过命令行指定算法如 RSA、密钥大小和有效期等参数来生成这个证书文件。第二步使用证书为应用签名在编译代码和资源文件生成未签名的 APK 文件后开发者需要为应用“盖章”。目前主流的做法是在 Android Studio 的 build.gradle 文件中配置签名信息包括证书路径、密码和别名等构建系统会在打包时自动完成签名。对于需要手动签名的场景开发者会使用 apksigner 或 jarsigner 命令行工具将数字证书与 APK 文件结合生成带有签名的 APK。第三步对齐优化Zipalign签名完成后开发者通常会使用 Android SDK 提供的 zipalign 工具对 APK 进行优化。这个步骤会对 APK 内部未压缩的数据进行 4 字节对齐从而减少运行时的内存消耗让应用在安卓设备上运行得更快、更高效。第四步验证签名最后开发者必须对生成的 APK 进行签名验证以确保签名过程没有出错。同样可以使用 apksigner verify 或 keytool 命令来查看 APK 的证书信息、签名版本如 v1、v2、v3以及是否有效。目前为了兼顾不同版本 Android 系统的安全性和兼容性开发者在配置时通常会同时启用 v1、v2 甚至 v3 签名方案。关于签名机制其实还有 v1、v2、v3 等不同版本的演进它们在保护范围和安全性上差别很大。需要我帮你梳理一下这几个版本的区别吗系统签名是要用安卓源码进行是的给应用进行系统签名即使用 platform 平台签名必须依赖 Android 系统源码环境。这主要是因为系统签名所使用的核心密钥文件如 platform.pk8 和 platform.x509.pem以及专用的签名工具如 signapk.jar都只存在于 Android 源码的编译目录中。在实际开发中开发者通常通过以下两种方式来利用源码环境完成系统签名方式一在源码环境中直接编译推荐开发者将应用的源码拷贝到 Android 源码的 packages/apps/ 目录下并在该应用的 Android.mk 配置文件中添加 LOCAL_CERTIFICATE : platform 这一行。随后使用 mm 命令进行编译构建系统会自动使用平台密钥为该应用签名生成的 APK 即为系统签名应用。方式二手动提取密钥进行重签名如果不想在庞大的源码环境中编译整个应用开发者也可以先通过 Android Studio 等工具正常编译出普通的 APK 文件。然后从 Android 源码的 build/target/product/security/ 目录下提取出 platform.pk8 和 platform.x509.pem 密钥文件并结合源码提供的 signapk.jar 工具通过执行命令如 java -jar signapk.jar platform.x509.pem platform.pk8 input.apk output.apk来手动给 APK 重新签名。重要安全限制系统签名密钥是高度敏感的必须在 Android 源码环境下妥善保管。使用这种方式生成的系统签名应用只能安装在由同一套系统源码编译出的 Android 系统上。如果将其安装到其他厂商如小米、华为等或未经授权的系统中系统会因为签名证书不匹配而拒绝安装这是 Android 保护系统底层安全的重要机制。系统签名应用装到自编译系统后想直接调用底层硬件权限比如相机、传感器通常还需要额外配置要不要说说这块的权限授权流程好的说说这块的权限授权流程系统签名应用Privileged System App获取底层硬件或系统级权限的流程与普通第三方应用有很大不同。它不再依赖用户在界面上的弹窗授权而是依赖于 Android 系统底层的白名单机制和默认授权策略。具体来说权限授权流程分为以下三个核心步骤声明系统共享用户 ID (Shared User ID)首先开发者需要在应用的 AndroidManifest.xml 文件中将应用配置为运行在系统进程中。这通常通过添加 android:sharedUserId“android.uid.system” 属性来实现。这一步是应用获取系统级身份的基础。配置特权权限白名单 (Priv-app Permissions Whitelist)对于需要 signature签名级或 privileged特权级的高危系统权限例如静默安装应用的 INSTALL_PACKAGES、修改安全设置的 WRITE_SECURE_SETTINGS 等仅仅将应用放在 /system/priv-app 目录下并使用平台签名是不够的。从 Android 10 开始系统引入了“强制特许权限白名单”机制。开发者必须在源码的特定配置文件如 privapp-permissions-platform.xml中显式地声明并放行该应用所需的所有特权权限。如果未在此白名单中配置应用即使拥有系统签名在启动时也会因权限校验失败而崩溃。处理敏感运行时权限 (Dangerous Permissions)对于涉及用户隐私的敏感硬件权限如相机 CAMERA、麦克风、位置等Android 出于隐私保护不会在安装时自动授予即便是系统签名应用也不例外。这类权限需要通过修改系统源码中的 DefaultPermissionGrantPolicy.java 文件来硬编码授权。在系统首次启动或恢复出厂设置时系统会执行该文件中的逻辑将指定的敏感权限默认授予核心的系统应用。总结系统签名应用调用底层权限本质上是将原本由“用户手动授权”的动作提前到了“系统源码编译与配置”阶段。开发者必须在源码层面完成身份绑定、特权白名单放行以及敏感权限的默认授予策略才能确保应用顺利调用底层能力。在实际开发中配置 privapp-permissions-platform.xml 时很容易因为格式或路径写错导致设备无法开机Bootloop。需要我帮你梳理一下这个白名单文件的正确配置模板和常见避坑指南吗为什么还要系统签名这是一个很好的追问。在前面的对话中我们已经聊了App 为什么需要签名但系统签名和普通开发者签名是两回事。简单来说系统签名是普通签名做不到的事情才需要它。具体原因可以归纳为以下几点普通签名拿不到的系统级权限Android 的权限体系分为四个等级normal普通、dangerous危险、signature签名级、signatureOrSystem签名或系统。前两种权限普通签名应用可以申请危险权限还需要用户弹窗同意。但像 INSTALL_PACKAGES静默安装、WRITE_SECURE_SETTINGS修改安全设置、ACCESS_FINE_LOCATION 在系统上下文中的权限等都标记为 signatureOrSystem 或 system 级别只有使用 platform 系统签名的应用才能获取。普通签名应用即使声明了这些权限系统也会直接拒绝授予。以系统进程身份运行通过系统签名应用可以设置 sharedUserId“android.uid.system”从而运行在系统进程中拥有和 SystemServer 相同的 UID。这意味着应用可以直接访问 /system、/data/system 等系统目录调用 Framework 层的隐藏 API不需要反射绕过与其他系统组件如 ActivityManagerService、PackageManagerService直接通信普通签名应用跑在独立的沙箱中UID 是随机分配的u0_aXX这些能力完全不可达。绕过安装来源验证和纯净模式系统签名应用被系统视为可信组件安装时不会触发未知来源警告也不会被华为、小米等厂商的纯净模式拦截。这对于企业定制 ROM、工业控制设备、物联网终端等场景非常关键——这些设备不需要应用商店审核机制但需要预装的应用拥有完整系统权限。开机自启动且不被系统杀死普通签名应用在后台很容易被 Android 的内存回收机制Low Memory Killer杀死而且开机后需要用户手动打开才能运行。系统签名应用可以被注册为系统服务或广播接收器随系统开机自动启动并且不会被普通的清理后台操作终止。这在车载系统、POS 机、智能音箱等需要 7×24 小时运行的场景中是刚需。修改系统全局设置普通签名应用无法修改 settings put global/secure 中的受保护项。而系统签名应用可以关闭或绕过屏幕锁定LockSettings修改默认输入法、默认浏览器等全局偏好设置 adb 调试权限、USB 调试模式控制飞行模式、Wi-Fi 开关等系统级数据共享多个使用相同系统签名的应用可以被系统视为同一程序共享 UID、共享 /data/data/ 目录下的数据文件夹、在同一进程中运行。这对于将系统功能拆分为多个 APK如 Google 的 GMS 套件非常有用普通签名做不到这一点。总结一句话 系统签名的本质是让应用获得半个系统的身份普通签名只是证明这个应用来自谁而系统签名证明的是这个应用就是系统的一部分。两者解决的安全层级完全不同。如果想进一步了解我可以帮你梳理一下系统签名在 Android 10 版本中的安全收紧趋势比如强制白名单、v4 签名方案或者在实际定制 ROM如 LineageOS中如何给第三方应用做系统签名的完整操作指南签名问题在一个项目中使用的apk以android.mk的方式编译到系统是需要签名如果想要安装 到目标机器上需要在目标机器系统的sdk中重新签名即重新编译再安装.apk即可这里按上面的做法后可以在目标机器的安装 打开Android.mk采用的模块如下#LOCAL_PATH:$(call my-dir)#include$(CLEAR_VARS)#LOCAL_MODULE:KehwinBLE#LOCAL_MODULE_TAGS:optional#LOCAL_PRIVILEGED_MODULE:true#LOCAL_SRC_FILES:./KehwinBLE.apk#LOCAL_MODULE_CLASS:APPS#LOCAL_MODULE_SUFFIX:$(COMMON_ANDROID_PACKAGE_SUFFIX)#LOCAL_CERTIFICATE:platform#include$(BUILD_PREBUILT)LOCAL_PATH:$(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE:AutoUpdate LOCAL_SRC_FILES:AutoUpdate.apk LOCAL_MODULE_CLASS:APPS LOCAL_MODULE_SUFFIX:.apk LOCAL_BUILT_MODULE_STEM:package.apk LOCAL_CERTIFICATE:platform include $(BUILD_PREBUILT)android 9LOCAL_PATH:$(my-dir)APK_NAME_FULL:$(shell cd $(LOCAL_PATH);ls-A|grep apk)APK_NAME:$(shell echo $(APK_NAME_FULL)|seds/.apk//g)$(warning--------------FullName$(APK_NAME_FULL)----Name$(APK_NAME))define get-all-libraries-module-name-in-subdirs $(sort $(shell cd $(LOCAL_PATH);rm-rf lib/dev/null;unzip $(APK_NAME_FULL)lib/*.so-d./dev/null;find-L $(1)-name*.so))endef ALL_LIBRARIES_MODULE_NAME:$(call get-all-libraries-module-name-in-subdirs,lib/armeabi-v7a)$(warning--------------ALL_LIBRARIES_MODULE_NAME:$(ALL_LIBRARIES_MODULE_NAME))include $(CLEAR_VARS)LOCAL_MODULE:BQB_V1.1.0.31_realtek LOCAL_MODULE_CLASS:APPS LOCAL_BUILT_MODULE_STEM:package.apk LOCAL_CERTIFICATE:platform LOCAL_PRIVILEGED_MODULE:trueLOCAL_SRC_FILES:$(LOCAL_MODULE).apk LOCAL_MODULE_SUFFIX:$(COMMON_ANDROID_PACKAGE_SUFFIX)LOCAL_MULTILIB:32LOCAL_PREBUILT_JNI_LIBS:$(ALL_LIBRARIES_MODULE_NAME)include $(BUILD_PREBUILT)