【Android安全】Google Hardware-backed Keystore | SafetyNet | 远程证明Remote Attestation

article/2025/9/20 4:22:38

Google Hardware-backed KeyStore Attestation 原理及流程

SafetyNet Hardware-backed Attestation

SafetyNet Hardware-backed Attestation:使用了Hardware-backed Keystore

SafetyNet 支持Software Attestation 和 Hardware-backed Attestation,根据设备是否支持Hardware Security Module (HSM)而定。
不同种类的Attestation,会导致Attestation Response的"evaluationType"字段值有所不同。
如果未进行Hardware-backed Attestation,或者Hardware-backed Attestation失败,则"ctsProfileMatch"值为false。

Hardware Security Module,包括ARM TrustZone、security co-processor like Google’s Titan M等。

对Google手机(例如Pixel)而言,Hardware-backed Attestation,基于Google Hardware-backed KeyStore实现。下面介绍其过程。

ro.boot.verifiedbootstate与Android Verified Boot

ro.boot.verifiedbootstate 代表着BootLoader的解锁状态。对于支持HSM(例如TEE)的手机而言,该值通常存储在HSM中。

以Pixel手机为例,相关的BootLoader验证过程是:
Pixel 在 TEE 中存储BootLoader状态(ro.boot.verifiedbootstate参数)。
当手机开机启动时,BootLoader会去加载Boot.img,如下图所示:
在这里插入图片描述

在加载Boot.img之前,BootLoader会去TEE中查询ro.boot.verifiedbootstate的值。

  • 如果值为locked,则BootLoader会继续执行 Android Verified Boot,检查Boot.img的签名,并拒绝加载非官签的Boot.img
  • 如果值为unlocked,则BootLoader将停止执行 Android Verified Boot,此时非官签的Boot.img也可以被加载

题外话:
常用的卡刷Root框架 Magisk,就是对Boot.img的patch。
patched Boot.img的签名自然是非官方的,所以能刷入patched Boot.img的前提是,设备的BootLoader已解锁。
详细原理参见:https://blog.csdn.net/qq_39441603?spm=1000.2115.3001.5343

关于Android Verified Boot,参考:
https://android.googlesource.com/platform/external/avb/+/master/README.md

SafetyNet对Hardware-backed Keystore的使用

从Keystore获取证书链

SafetyNet框架中的DroidGuard VM会从Google Server接收到一段bytecode,并执行这段bytecode。

这段bytecode的执行过程,会查询到一些系统属性。后续,这些属性会被发送给Google Server,用以判定设备完整性。

系统属性中包含一个证书链,该证书链是由Hardware-backed Keystore返回的。

如果想获取该证书链,可以调用getCertificateChain()。
例如:

Certificate certificates[] = keyStore.getCertificateChain(alias);

方法的文档:
https://developer.android.com/reference/java/security/KeyStore#getCertificateChain(java.lang.String)

Google security-key-attestation官方文档:
https://developer.android.com/training/articles/security-key-attestation#verifying

下面介绍:该证书链如何生成、该证书链是什么、该证书链有什么用

该证书链的内容及生成过程

本质上:该证书链相当于合法TEE签名过的ro.boot.verifiedbootstate等值,表明这些值是认证过的,是未被篡改的。
该合法TEE的私钥对应的公钥是Google备案过的。

该证书链的生成过程如下:
(1)Google相当于Root CA,手机生产商OEM相当于中间CA,TEE相当于叶CA

(2)TEE是在Google备案的:
Google用Google私钥签名Google公钥,形成自签名的根证书1;
Google用Google私钥签名OEM公钥,形成证书2,Extensions 中包含ro.boot.verifiedbootstate等值;
OEM用OEM私钥签名TEE公钥,形成证书3;

(3)当DroidGuard请求证书链时,TEE生成一张证书4,证书4的
而后,TEE用TEE私钥签名此证书4。

(4)TEE返回一个证书链,包括:

  • 证书4(KeyStore私钥签名)
  • 证书3(内容为KeyStore公钥,OEM私钥签名)
  • 证书2(内容为OEM公钥,Extensions 包含verifiedbootstate,Google私钥签名)
  • 证书1(Root Certificate)(内容为Google公钥,Google私钥签名)

需要注意的是:对证书的签名,是对整个证书文件的签名(包括元数据和公钥),而不只是对证书中公钥的签名。所以证书的元数据中的Extensions也在被签名的范畴,因此Extensions中的内容也被认证了。

On a separate server that you trust, obtain a reference to the ASN.1 parser library that is most appropriate for your toolset. Find the nearest certificate to the root that contains the attestation certificate extension; do not assume this to be the leaf certificate. Use the parser to extract the attestation certificate extension data from that certificate.
https://developer.android.com/training/articles/security-key-attestation#verifying

该证书链的验证过程

应在服务器端进行,下面说明其在成功情况下的过程。

(1)获取Google根证书列表
https://developer.android.com/training/articles/security-key-attestation#root_certificate

(2)验证证书1在上述列表中
验证证书2的签名和证书1中的公钥对得上
验证证书3的签名和证书2中的公钥对得上
验证证书4的签名和证书3中的公钥对得上
由此可说明证书4的文件内容非伪造

(3)提取证书2中的Extensions,检查其中的ro.boot.verifiedbootstate等值,据此判断设备的状态(例如bootloader是否解锁、是否rooted等),给出"basicIntegrity"、"ctsProfileMatch"的结论

官方给出的验证步骤

Google官方文档:https://developer.android.com/training/articles/security-key-attestation#verifying

(1)Use a KeyStore object’s getCertificateChain() method to get a reference to the chain of X.509 certificates associated with the hardware-backed keystore.
客户端使用KeyStore对象的getCertificateChain()方法拿到证书链(和hardware-backed keystore相关联)

(2)Check each certificate’s validity using an X509Certificate object’s checkValidity() method. Also verify that the root certificate is trustworthy.
验证每一个证书的有效性

(3)On a separate server that you trust, obtain a reference to the ASN.1 parser library that is most appropriate for your toolset. Use this parser to extract the attestation certificate extension data, which appears within the first element of the certificate chain.
提取证书的extension data

(4)Compare the extension data that you’ve retrieved from your ASN.1 parser with the set of values that you expect the hardware-backed key to contain.
将提取出来的extension data和expected values进行比较
(也就是检查extension data中的verifiedbootstate等值)

(3)和(4)应该在服务端进行
服务端实现示例:https://github.com/google/android-key-attestation/tree/master/server


http://chatgpt.dhexx.cn/article/BmOI2sOx.shtml

相关文章

SafetyNet简要梳理

目录 前序 2 什么是SafetyNet校验? 2 Safetynet工作原理 2 监控及校验内容 2 实现方式 3 参考文献: 4 前序 由于近年来Android支付应用的兴起,一些人在root过的手机上发现该类支付性质的应用无法使用。原来&#xf…

什么是跨域?以及解决方案

现在的web项目,很多都是前后端分离,特别容易出现跨域问题 那么什么是跨域问题呢?本篇文章带你彻底从本质上弄明白什么是跨域问题以及如何解决 一、跨域有什么现象 首先我们看一下现象,如何出现的跨域问题。例: 前段&#xff1a…

跨域问题与解决方案

什么是跨域问题? 跨域问题的产生,源自浏览器的同源策略:SOP(Same origin policy)。 同源策略是由 Netscape 提出的一个著名的安全策略,它是浏览器最核心也是最基本的安全功能,所有支持 JavaSc…

跨域常见的解决方案

目录 一:什么是跨域 二:为什么会跨域 三:跨域的解决方案 1.代理服务器 1.1.生产环境 1.2.开发环境 2.JSONP 3.CORS 一:什么是跨域 跨域是指浏览器在向一个服务器发送请求时,该请求的地址与当前页面的地址不同…

React跨域解决方案

一、业务场景: 前后端数据交互时会存在跨域的情况,这个时候就比较难受。传统的解决方案有三种,分别是 Jsonp:但是只能处理get请求 后端CORS:配置注解CrossOrigin(用的最多) 反向代理 &#xff1…

10 种跨域解决方案(附终极方案)

写在前面 嗯。又来了,又说到跨域了,这是一个老生常谈的话题,以前我觉得这种基础文章没有什么好写的,会想着你去了解底层啊,不是很简单吗。但是最近在开发一个 vscode 插件 发现,当你刚入门一样东西的时候&…

可能是最好的跨域解决方案了

今天我们来聊一个老生常谈的话题,跨域!又是跨域,烦不烦 ?网上跨域的文章那么多,跨的我眼睛都疲劳了,不看了不看了 🤣 别走...我尽量用最简单的方式将常见的几种跨域解决方案给大家阐释清楚&…

跨域问题解决方案

跨域问题产生的前提条件 必须要有浏览器,没有浏览器,是不存在跨域问题。浏览器为了安全问题,限制了跨域访问,不允许跨域请求资源。 跨域 浏览器从一个域名的网页去请求另一个域名的资源,域名、端口、协议有任何一个…

跨域理解与解决方案

一 、跨域是啥 为啥会发生? 跨域本质是浏览器基于同源策略的一种安全手段,是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础…

Vue中的跨域解决方案

前言 跨域是因为浏览器存在对不同源页面数据接收的限制。这种限制就是浏览器的同源策略。 同源策略是浏览器的安全机制,跨域的原理就是通过各种方式避开浏览器的安全机制 使用 在项目开发时,对跨域的概念仅限于了解,所以没有注重过程&#xf…

Vue跨域解决方案

文章目录 前言一、跨域是什么?二、解决跨域的办法 前言 跨域错误信息 Access to XMLHttpRequest at ‘http://192.168.2.92:3000/api/b/home’ from origin ‘http://localhost:8080’ has been blocked by CORS policy: Response to preflight request doesn’t …

跨域的几种解决方案(详细)

跨域的几种解决方案 1.什么是跨域2.演示用axios请求网易新闻地址,发现跨域出错3.解决跨域方式3.1 jsonp方式3.2 cors方式3.3 proxy代理转发 1.什么是跨域 .网页所在url的协议、域名、端口号,和Ajax请求url的协议、域名、端口号有一个对应不上&#xff0…

跨域9大解决方案(超详细) 总结

前面的话 我们经常听到跨域这词,这是由于浏览器同源策略限制的一类请求场景。这样做的目的使得 浏览器不容易受到攻击。 推荐文章:九种跨域方式实现原理(完整版) 什么是同源策略? 同源策略(Same origin…

前端跨域解决方案

文章目录 注意,本文已迁移 1.同源政策2.跨域解决方案2.1 CORS普通跨域请求:只需服务端设置Access-Control-Allow-Origin即可携带cookie跨域请求:前后端都需设置 2.2 postMessage跨域2.3 JSONP原理缺点数据格式jsonp跨域实现 2.4 WebSocket属性…

解决跨域的三种方案

解决跨域的三种方案 到目前为止,我们编写的 GET 和 POST 接口,存在一个很严重的问题:不支持跨域请求 解决接口跨域问题的方案主要有三种 CORS (主流的解决方案,推荐使用) 代理 (推荐使用) JSONP (有缺陷的解决方案&#xff1a…

跨域的五种解决方案详解

1.跨域解决方案一:cors技术 CORS :全称cross origin resource share (资源共享) 工作原理: 服务器 在返回响应报文的时候,在响应头中 设置一个允许的header res.setHeader(‘Access-Control-Allow-Origin’, ‘*’) CORS :全称…

Java中parseInt用法(double类似)

1.将字符直接解析为十进制数进行输出 2.如果方法有两个参数, 使用第二个参数指定的基数,将字符串参数解析为有符号的10进制整数。(所谓指定基数:就是将字符串指定为2,8,16等进制数,然后用解析为…

javascript:parseInt用法,特殊用法,进制转换

parseInt( string,radix ) 一、功能: 除了我们众所周知的字符串转换为整数以外,还涉及到进制问题: 将 [ 指定进制的 ] 字符串转换为十进制整数型 用汉语翻一下这个方法: 二、参数: 1、string: 要解析的字符串&a…

前端JS字符串转数值 Number和parseInt用法

Number() 只包含数值的字符串字符串为空则为0 parseInt() 字符串不能为空字符串第一个必须为数值从第一个数值开始取,到最后一个连续数值结束

java中Integer.parseInt用法详细分析(全)

目录 前言函数讲解 前言 将数字字符串转化成原生整型数据 属于java.lang.Integer 是原生类型整型的包裹类 函数讲解 1.parseInt(String s) 将字符串s转换为十进制的数字,默认为十进制 public static void main(String[] args) {int numInteger.parseInt("10…