目录
一、APK应用签名
1、什么是APK应用签名?
1.1 目的和作用?
1.2 长什么样子?
2、APK应用签名使用流程
步骤一:如何生成APK应用签名文件?
步骤二:如何集成APK应用签名文件?
步骤三:如何使用APK应用签名文件?
3、相关案例
案例一:CtsSecurityTestCases
案例二:因为APK应用签名不匹配,导致OTA无法正常升级
二、Google KEY
1、什么是Google KEY?
1.1 KeyStore的发展历史
1.2 为什么要密钥认证?
2、KeyStore架构
3、Google KEY使用流程
步骤一:Google KEY的申请
步骤二:Google KEY的切割
步骤三:Google KEY的写入
重点说明:Google KEY是否必须要写入?
4、相关案例
案例一:没有写入Google KEY引入多例XTS问题
案例二:keystore数据库被损坏,导致所有应用无法打开
三、EFUS KEY
四、Widevine KEY
Android中涉及到KEY和秘钥相关的地方有好几处,而且还比较容易混淆。这里记录一下我们常用的一些KEY以及他们的目的和作用。
一、APK应用签名
1、什么是APK应用签名?
他是google的一套原生机制,google官方对其详细说明了一下:https://source.android.com/docs/core/ota/sign_builds?hl=zh-cn
1.1 目的和作用?
- 为什么要针对apk包进行签名?同google官方网站的描述,如果你更新apk的时候,系统会检测你的apk的签名秘钥是否和系统指定的签名秘钥匹配,如果不匹配,系统将会拒绝安装改应用,这样能够保证被更新的应用是没有掉过包的。
- 为什么要针对ota包进行签名?同前面提到的apk应用一样,OTA包其实也可以简单的理解为一个大型apk,我们在安装OTA包之前需要对其进行校验(通过RecoverySystem.verifyPackage()),如果签名秘钥对不匹配,讲拒绝OTA升级,同样保证被更新的OTA是没有掉过包的。
1.2 长什么样子?
每个密钥都包含两个文件:一个是扩展名为 .x509.pem 的证书,另一个是扩展名为 .pk8 的私钥。 私钥需要加以保密,并用于对 apk 包进行签名。 密钥本身也可能受密码保护。相比之下,证书只包含公开的一半密钥,因此可以大范围地分发。证书用于验证某个 apk 包是否由相应的私钥进行签名。
标准 Android build 使用四个密钥,所有这些密钥都位于 build/target/product/security
中
- testkey:适用于未另外指定密钥的 apk 包的通用默认密钥。
- platform:适用于核心平台所包含的 apk 包的测试密钥。
- shared:适用于家庭/联系人进程中的共享内容的测试密钥。
- media:适用于媒体/下载系统所包含的 apk 包的测试密钥。
- networkstack:适用于网络系统所包含的 apk 包的测试密钥
2、APK应用签名使用流程
步骤一:如何生成APK应用签名文件?
在android根目录/build/target/product/security/有详细说明如何生成秘钥对,其中
在项目开发过程中,我们通常需要更换上面的秘钥对,使用客户提供或者我们自己的秘钥对,生成方式如上。
步骤二:如何集成APK应用签名文件?
我们可以通过宏变量PRODUCT_DEFAULT_DEV_CERTIFICATE来指定如上步骤生成的签名文件的路径。如ChatGPT的回答:
步骤三:如何使用APK应用签名文件?
- Android编译构建的时候引入KEY
- 应用集成的时候指定使用的KEY
include $(CLEAR_VARS)
LOCAL_MODULE := AOSPLauncherR
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_MODULE_CLASS := APPS
LOCAL_CERTIFICATE := platform //指定平台签名
LOCAL_PRIVILEGED_MODULE := true
LOCAL_REQUIRED_MODULES := privapp_permissions_AOSPLauncherR.xml
LOCAL_OVERRIDES_PACKAGES := Home Launcher2 Launcher3 \
Launcher3QuickStep Launcher3Go Launcher3QuickStepGo \
MtkLauncher3 MtkLauncher3QuickStep MtkLauncher3Go MtkLauncher3QuickStepGo MtkLauncher3GoIconRecents
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
LOCAL_MODULE := privapp_permissions_AOSPLauncherR.xml
LOCAL_MODULE_CLASS := ETC
LOCAL_PRODUCT_MODULE := true
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
这里集成的AOSPLauncherR因为是平台的应用,LOCAL_CERTIFICATE = platform,因此编译构建的时候针对AOSPLancherR应用会使用步骤一中指定的plat签名文件进行签名
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := MobileFeliCaSettingApp
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_MODULE_PATH := $(TARGET_OUT_APPS)
# indicate to generate .odex file in special built/core/prebuilt.mk
LOCAL_DEX_PREOPT:=true
include $(BUILD_PREBUILT)
这里集成的MobileXXX应用是三方应用,使用LOCAL_CERTIFICATE := PRESIGNED,因此编译构建的时候使用的是testKey?
3、相关案例
案例一:CtsSecurityTestCases
如上报错日志表示一堆应用使用了android默认的应用签名,解决方案就是生成新的应用签名文件
案例二:因为APK应用签名不匹配,导致OTA无法正常升级
二、Google KEY
1、什么是Google KEY?
Android的密钥库已经有很多年了,它为应用程序开发者提供了一种使用加密密钥进行验证和加密的方法。 Keystore将密钥保留在应用程序的进程空间之外,以便应用程序不会无意中将其泄露给可能被钓鱼的用户,通过其他渠道泄漏,或者在应用程序遭到破坏时。 许多设备还为安全硬件中的密钥库密钥提供了基于硬件的安全性,从而将密钥材料完全保留在Android系统之外,从而即使Linux内核泄露也不会泄露密钥材料。 在绝大多数Android设备中,安全硬件是主CPU的特殊模式,硬件强制与Linux内核和Android用户空间隔离。比如基于Arm的TrustZone技术实现的TEE安全操作系统, 或者,某些设备使用单独的安全微处理器。比如SE芯片。
Android提供的API允许应用程序确定给定的密钥库密钥是否在安全硬件中,但是如果操作系统受到威胁,这些API可能不可靠。 密钥证明Key attestation为设备的安全硬件提供了一种方法,用于验证非对称密钥是否处于安全硬件中,以防止对Android操作系统的破坏。
1.1 KeyStore的发展历史
Keystore最初是在Android 4.0中引入的,而且密钥是用用户的密码加密的。 在Android 4.1中增加了使用设备安全硬件的基础设施。
直到Android 6.0,Keystore支持RSA和ECDSA。 在Android 6.0中,Keystore得到了显着增强,增加了对AES和HMAC的支持。 此外,加密操作的其他关键要素(如RSA填充1和AES块链接2模式)也被转移到安全的硬件中。
在Android 6.0中,Keystore也获得了限制特定密钥的使用方式的能力。 可以应用的最明显有用的限制是用户身份验证绑定。 这允许密钥的使用被“绑定”到用户的密码 - 它们的PIN,图案或密码 - 或指纹。 对于密码认证绑定,应用程序开发人员可以在几秒钟内指定超时。 如果用户上次输入的密码超过了指定的时间,安全硬件将拒绝任何使用该密钥的请求。 每次使用密钥时,指纹绑定密钥都需要新的用户身份验证。
其他更技术性的限制也可以应用于Android 6.0及更高版本。 特别是在密钥创建或导入时,有必要指定可以使用密钥的加密目的(加密,解密,签名或验证)以及填充和块模式,摘要,熵源 用于初始化向量或随机数,以及密码操作的其他细节。 由于指定的信息是永久性的,并且密码上与密钥材料绑定,所以密钥库不允许以任何其他方式使用密钥。 因此,获得应用程序或系统控制权的攻击者不能误用密钥。 为了帮助防止攻击,开发人员应该为给定的密钥指定可能的最窄范围。
Android密钥库最重要的变化之一是在Android 7.0中引入的。 使用安全锁屏启动Android 7.0+的新设备必须具有安全的硬件,并支持基于硬件的密码验证和密钥库密钥。 在Android 7.0之前,安全的硬件支持非常普遍,但是在未来的几年里,它将会变得普遍。
在Android 8.0中,所有安装了Google Play的新设备都必须提供关键证明。
1.2 为什么要密钥认证?
简单来说,Google的keystore机制提供了一套密钥管理机制,应用越来多,越来越重要了,但是密钥认证问题如果不解决,这一切都是不可靠的!
- keymaster HAL可以是假的,你没办法判断系统HAL以下是否真实,简单来说,如果没有使用TEE,你也可以通过keymaster HAL欺骗Framwork层。
- 即使设备是正常的,应用也可以欺骗第三方。
假设您正在开发一个应用程序,为银行的客户提供银行余额,交易历史记录和账单支付系统。 安全是重要的。 您不希望任何拿起用户手机的人访问他们的银行帐户。 一种方法是使用用户的网站密码。 但是这对用户来说通常是不方便的,因为网站经常需要长而复杂的密码,这在小的触摸屏上是不方便的。
使用Android Keystore,可以生成非对称身份验证密钥,例如256位ECDSA密钥,并让每个用户使用其复杂的Web密码登录一次,然后在银行的客户帐户数据库中注册公钥。 每次打开应用程序时,您都可以使用该ECDSA密钥执行质询 - 响应身份验证协议。 此外,如果您将密钥认证绑定,则用户每次打开应用程序时都可以使用其锁屏密码或指纹进行身份验证。 这使得他们可以在手机上使用更简单,更方便的认证机制。
如果攻击者危及Android并尝试提取密钥,则他们不会成功,因为密钥在安全硬件中。
作为应用程序开发人员,密钥认证允许您在服务器上验证您的应用程序所请求的ECDSA密钥实际上是否安全地存在于硬件中。 请注意,在您的应用程序本身中使用证明是没有意义的。 如果Android操作系统是不妥协和可信的,那么您可以使用6.0中引入的KeyInfo类来发现密钥是否在安全硬件中。 如果它被攻破,那么这个API和你在设备上验证证明的任何尝试都是不可靠的。
请注意,密钥证明不同于SafetyNet认证。 他们是相同的概念,但是证明不同的事物来自不同的地方。 密钥库密钥证明确认密钥存在于安全的硬件中并具有特定的特征。 SafetyNet认证确认设备是真实的(不是仿真器),并且运行已知的软件。 SafetyNet使用Keystore密钥证明,所以如果你想了解设备的完整性使用。 如果您想确认您的密钥是否在安全硬件中,请使用密钥认证。
2、KeyStore架构
当前比较新的Android 例如S的系统默认使用了keymaster的机制,如下图,Android系统中的应用进程加解密的逻辑处理,通过binder方式和HAL接口在TEE这个安全环境下(独立于linux/android系统的上下文,这个下节将会提到)执行。
KeyStore的源码解读参考专栏:https://blog.csdn.net/weixin_42135087/article/details/124569112
这里我简单的总结一下:
- TEE:TEE是独立于Android和Linux内核的一套系统,他和Linux内核一样,由bootloader启动。他给整个设备提供了一套安全的环境,这里说的安全并不仅仅指软件,还特别包含加密硬件的相关支撑。即高通芯片/MTK芯片他们需要提供这样的硬件加密能力,TEE就是一套闭源的安全系统,他可以使用调用芯片的这些硬件加密能力。当然他们之间可能存在一些接口或者协议,就跟ARM架构和Linux系统之间一样。重点:TEE是提供安全的软硬件系统,站在软件的角度上他和Linux内核是同一级别的。
- KeymasterHAL:这里说的KeymasterHAL是运行在Android世界里面,它跟普通的硬件抽象层HAL服务没有本质的区别,唯一的区别就是他可以通过Linux内核去和TEE进行数据通信。
- KeyStoreService:它被init进程启动,即和其他native进程也没有本质的区别,但是他维护了一个秘钥相关的复杂数据库,同事完成了一些加密,解密,秘钥查询等事情。例如指纹锁/图案锁等涉及到的秘钥的一些信息数据被存储在这个数据库里面,这些操作都需要通过KeymasterHAL去和TEE进行交互,实际操作的地方还是在TEE空间里面。
- KeyStore:作为KeyStoreService为framework层提供的客户端,即上层应用可以通过KeyStore来调用native层的keystoreservice
- Application:需要使用秘钥相关的应用,常见的有锁屏应用、生物锁、银行金融APP等
3、Google KEY使用流程
步骤一:Google KEY的申请
- 每个device单独申请keybox(attestation key),首先需要去跑CTS白名单
- 根据CTS白名单的报告提交到google官方网站进行keybox申请
步骤二:Google KEY的切割
- google审核通过之后会返回一个keybox,为了工厂生产的需要,我们需要对其进行切割
步骤三:Google KEY的写入
- 切割之后的key,需要通过工具写入到android设备里面,通常进入meta模式来进行写key
重点说明:Google KEY是否必须要写入?
google key可以不写入,通常我们在调试开发中很少写这个东西,不影响我们的基本功能使用。但是正常出货的设备或者需要做XTS的设备需要写google key,因为他会导致一些功能无法使用。